summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/autofill/Android.bp1
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java28
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/AutofillTestWatcher.java133
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java34
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/MyAutofillService.java20
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java207
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java73
-rw-r--r--api/current.txt60
-rw-r--r--api/module-lib-current.txt1
-rw-r--r--api/system-current.txt80
-rw-r--r--api/test-current.txt4
-rw-r--r--cmds/statsd/src/condition/ConditionTracker.h6
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp47
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.h16
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp32
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h50
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp21
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp247
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h79
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp301
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h63
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp599
-rw-r--r--core/java/android/app/ActivityManagerInternal.java27
-rw-r--r--core/java/android/app/ActivityThread.java450
-rw-r--r--core/java/android/app/AppOpsManager.java84
-rw-r--r--core/java/android/app/ClientTransactionHandler.java54
-rw-r--r--core/java/android/app/ContextImpl.java7
-rw-r--r--core/java/android/app/IActivityManager.aidl7
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl6
-rw-r--r--core/java/android/app/LocalActivityManager.java43
-rw-r--r--core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java12
-rw-r--r--core/java/android/app/servertransaction/ActivityLifecycleItem.java2
-rw-r--r--core/java/android/app/servertransaction/ActivityRelaunchItem.java30
-rw-r--r--core/java/android/app/servertransaction/ActivityResultItem.java11
-rw-r--r--core/java/android/app/servertransaction/ActivityTransactionItem.java69
-rw-r--r--core/java/android/app/servertransaction/DestroyActivityItem.java8
-rw-r--r--core/java/android/app/servertransaction/EnterPipRequestedItem.java8
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java3
-rw-r--r--core/java/android/app/servertransaction/MoveToDisplayItem.java13
-rw-r--r--core/java/android/app/servertransaction/NewIntentItem.java11
-rw-r--r--core/java/android/app/servertransaction/PauseActivityItem.java9
-rw-r--r--core/java/android/app/servertransaction/ResumeActivityItem.java8
-rw-r--r--core/java/android/app/servertransaction/StartActivityItem.java9
-rw-r--r--core/java/android/app/servertransaction/StopActivityItem.java8
-rw-r--r--core/java/android/app/servertransaction/TopResumedActivityChangeItem.java26
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutor.java12
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/android/content/om/TEST_MAPPING14
-rw-r--r--core/java/android/content/pm/ActivityInfo.java10
-rw-r--r--core/java/android/content/pm/ApkChecksum.java40
-rw-r--r--core/java/android/content/pm/Checksum.java27
-rw-r--r--core/java/android/content/pm/PackageInstaller.java3
-rw-r--r--core/java/android/content/pm/PackageManager.java3
-rw-r--r--core/java/android/content/pm/TEST_MAPPING14
-rw-r--r--core/java/android/content/res/Configuration.java63
-rw-r--r--core/java/android/content/res/TEST_MAPPING14
-rw-r--r--core/java/android/hardware/display/DisplayManager.java24
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java26
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl6
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTrigger.java184
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTriggerModule.java34
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java23
-rw-r--r--core/java/android/os/incremental/IIncrementalService.aidl2
-rw-r--r--core/java/android/os/incremental/IncrementalFileStorages.java10
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java5
-rw-r--r--core/java/android/permission/PermissionManager.java15
-rw-r--r--core/java/android/provider/DeviceConfig.java9
-rw-r--r--core/java/android/provider/Settings.java23
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java44
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java14
-rw-r--r--core/java/android/view/IWindowSession.aidl42
-rw-r--r--core/java/android/view/InsetsState.java22
-rw-r--r--core/java/android/view/View.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java85
-rw-r--r--core/java/android/view/WindowManagerImpl.java19
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java4
-rw-r--r--core/java/android/window/WindowMetricsHelper.java17
-rw-r--r--core/java/com/android/internal/app/ISoundTriggerService.aidl78
-rw-r--r--core/java/com/android/internal/app/ISoundTriggerSession.aidl68
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl78
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl95
-rw-r--r--core/java/com/android/internal/policy/DecorView.java92
-rw-r--r--core/proto/android/content/configuration.proto1
-rw-r--r--core/proto/android/providers/settings/config.proto5
-rw-r--r--core/proto/android/providers/settings/global.proto2
-rw-r--r--core/proto/android/providers/settings/secure.proto2
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/values-am/strings.xml4
-rw-r--r--core/res/res/values-ar/strings.xml2
-rw-r--r--core/res/res/values-be/strings.xml26
-rw-r--r--core/res/res/values-gu/strings.xml6
-rw-r--r--core/res/res/values-in/strings.xml2
-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-nl/strings.xml18
-rw-r--r--core/res/res/values-pa/strings.xml2
-rw-r--r--core/res/res/values-uz/strings.xml2
-rw-r--r--core/res/res/values/attrs_manifest.xml6
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java62
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java64
-rw-r--r--core/tests/coretests/src/android/content/ContextTest.java38
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java15
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java15
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java338
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java10
-rw-r--r--data/etc/platform.xml7
-rw-r--r--data/etc/services.core.protolog.json24
-rw-r--r--data/fonts/fonts.xml29
-rw-r--r--data/keyboards/Vendor_27f8_Product_0bbe.kl54
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java5
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp9
-rw-r--r--location/java/android/location/LocationManager.java20
-rw-r--r--media/Android.bp24
-rw-r--r--media/java/android/media/DrmInitData.java6
-rw-r--r--media/java/android/media/ExifInterface.java23
-rw-r--r--media/java/android/media/ExifInterfaceUtils.java18
-rw-r--r--media/java/android/media/MediaExtractor.java4
-rw-r--r--media/java/android/media/permission/ClearCallingIdentityContext.java58
-rw-r--r--media/java/android/media/permission/CompositeSafeCloseable.java40
-rw-r--r--media/java/android/media/permission/Identity.aidl32
-rw-r--r--media/java/android/media/permission/IdentityContext.java100
-rw-r--r--media/java/android/media/permission/PermissionUtil.java250
-rw-r--r--media/java/android/media/permission/SafeCloseable.java (renamed from tests/utils/testutils/java/android/view/test/InsetsModeSession.java)24
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerDetector.java12
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerManager.java53
-rw-r--r--media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl53
-rw-r--r--non-updatable-api/current.txt60
-rw-r--r--non-updatable-api/module-lib-current.txt1
-rw-r--r--non-updatable-api/system-current.txt79
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java4
-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.java2
-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.java27
-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/InputDevices/res/values-af/strings.xml2
-rw-r--r--packages/InputDevices/res/values-am/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ar/strings.xml5
-rw-r--r--packages/InputDevices/res/values-as/strings.xml5
-rw-r--r--packages/InputDevices/res/values-az/strings.xml5
-rw-r--r--packages/InputDevices/res/values-b+sr+Latn/strings.xml5
-rw-r--r--packages/InputDevices/res/values-be/strings.xml5
-rw-r--r--packages/InputDevices/res/values-bg/strings.xml2
-rw-r--r--packages/InputDevices/res/values-bn/strings.xml5
-rw-r--r--packages/InputDevices/res/values-bs/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ca/strings.xml2
-rw-r--r--packages/InputDevices/res/values-cs/strings.xml2
-rw-r--r--packages/InputDevices/res/values-da/strings.xml2
-rw-r--r--packages/InputDevices/res/values-de/strings.xml2
-rw-r--r--packages/InputDevices/res/values-el/strings.xml2
-rw-r--r--packages/InputDevices/res/values-en-rAU/strings.xml1
-rw-r--r--packages/InputDevices/res/values-en-rCA/strings.xml1
-rw-r--r--packages/InputDevices/res/values-en-rGB/strings.xml1
-rw-r--r--packages/InputDevices/res/values-en-rIN/strings.xml1
-rw-r--r--packages/InputDevices/res/values-en-rXC/strings.xml1
-rw-r--r--packages/InputDevices/res/values-es-rUS/strings.xml2
-rw-r--r--packages/InputDevices/res/values-es/strings.xml2
-rw-r--r--packages/InputDevices/res/values-et/strings.xml2
-rw-r--r--packages/InputDevices/res/values-eu/strings.xml2
-rw-r--r--packages/InputDevices/res/values-fa/strings.xml2
-rw-r--r--packages/InputDevices/res/values-fi/strings.xml5
-rw-r--r--packages/InputDevices/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/InputDevices/res/values-fr/strings.xml2
-rw-r--r--packages/InputDevices/res/values-gl/strings.xml2
-rw-r--r--packages/InputDevices/res/values-gu/strings.xml2
-rw-r--r--packages/InputDevices/res/values-hi/strings.xml2
-rw-r--r--packages/InputDevices/res/values-hr/strings.xml2
-rw-r--r--packages/InputDevices/res/values-hu/strings.xml2
-rw-r--r--packages/InputDevices/res/values-hy/strings.xml2
-rw-r--r--packages/InputDevices/res/values-in/strings.xml2
-rw-r--r--packages/InputDevices/res/values-is/strings.xml2
-rw-r--r--packages/InputDevices/res/values-it/strings.xml2
-rw-r--r--packages/InputDevices/res/values-iw/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ja/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ka/strings.xml2
-rw-r--r--packages/InputDevices/res/values-kk/strings.xml5
-rw-r--r--packages/InputDevices/res/values-km/strings.xml2
-rw-r--r--packages/InputDevices/res/values-kn/strings.xml5
-rw-r--r--packages/InputDevices/res/values-ko/strings.xml5
-rw-r--r--packages/InputDevices/res/values-ky/strings.xml5
-rw-r--r--packages/InputDevices/res/values-lo/strings.xml2
-rw-r--r--packages/InputDevices/res/values-lt/strings.xml2
-rw-r--r--packages/InputDevices/res/values-lv/strings.xml5
-rw-r--r--packages/InputDevices/res/values-mk/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ml/strings.xml5
-rw-r--r--packages/InputDevices/res/values-mn/strings.xml5
-rw-r--r--packages/InputDevices/res/values-mr/strings.xml5
-rw-r--r--packages/InputDevices/res/values-ms/strings.xml5
-rw-r--r--packages/InputDevices/res/values-my/strings.xml2
-rw-r--r--packages/InputDevices/res/values-nb/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ne/strings.xml5
-rw-r--r--packages/InputDevices/res/values-nl/strings.xml4
-rw-r--r--packages/InputDevices/res/values-or/strings.xml5
-rw-r--r--packages/InputDevices/res/values-pa/strings.xml5
-rw-r--r--packages/InputDevices/res/values-pl/strings.xml2
-rw-r--r--packages/InputDevices/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/InputDevices/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/InputDevices/res/values-pt/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ro/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ru/strings.xml2
-rw-r--r--packages/InputDevices/res/values-si/strings.xml2
-rw-r--r--packages/InputDevices/res/values-sk/strings.xml5
-rw-r--r--packages/InputDevices/res/values-sl/strings.xml2
-rw-r--r--packages/InputDevices/res/values-sq/strings.xml2
-rw-r--r--packages/InputDevices/res/values-sr/strings.xml5
-rw-r--r--packages/InputDevices/res/values-sv/strings.xml2
-rw-r--r--packages/InputDevices/res/values-sw/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ta/strings.xml5
-rw-r--r--packages/InputDevices/res/values-te/strings.xml2
-rw-r--r--packages/InputDevices/res/values-th/strings.xml2
-rw-r--r--packages/InputDevices/res/values-tl/strings.xml2
-rw-r--r--packages/InputDevices/res/values-tr/strings.xml2
-rw-r--r--packages/InputDevices/res/values-uk/strings.xml2
-rw-r--r--packages/InputDevices/res/values-ur/strings.xml2
-rw-r--r--packages/InputDevices/res/values-uz/strings.xml5
-rw-r--r--packages/InputDevices/res/values-vi/strings.xml2
-rw-r--r--packages/InputDevices/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/InputDevices/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/InputDevices/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/InputDevices/res/values-zu/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml10
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml12
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java6
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java36
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml27
-rw-r--r--packages/SystemUI/res/values-am/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml31
-rw-r--r--packages/SystemUI/res/values-as/strings.xml27
-rw-r--r--packages/SystemUI/res/values-az/strings.xml27
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml27
-rw-r--r--packages/SystemUI/res/values-be/strings.xml29
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml29
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml27
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml27
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml31
-rw-r--r--packages/SystemUI/res/values-da/strings.xml29
-rw-r--r--packages/SystemUI/res/values-de/strings.xml27
-rw-r--r--packages/SystemUI/res/values-el/strings.xml29
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml20
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml20
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml20
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml20
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml20
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml37
-rw-r--r--packages/SystemUI/res/values-es/strings.xml31
-rw-r--r--packages/SystemUI/res/values-et/strings.xml27
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml27
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml27
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml27
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml27
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml27
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml33
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml29
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml33
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml27
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml27
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml29
-rw-r--r--packages/SystemUI/res/values-in/strings.xml27
-rw-r--r--packages/SystemUI/res/values-is/strings.xml27
-rw-r--r--packages/SystemUI/res/values-it/strings.xml29
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml29
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml37
-rw-r--r--packages/SystemUI/res/values-km/strings.xml31
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml29
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml29
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml27
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml29
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml29
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml31
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml27
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml29
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml27
-rw-r--r--packages/SystemUI/res/values-my/strings.xml27
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml29
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml31
-rw-r--r--packages/SystemUI/res/values-or/strings.xml29
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml27
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml27
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml33
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml29
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml33
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml29
-rw-r--r--packages/SystemUI/res/values-si/strings.xml27
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml27
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml29
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml27
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml27
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml27
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml27
-rw-r--r--packages/SystemUI/res/values-te/strings.xml29
-rw-r--r--packages/SystemUI/res/values-th/strings.xml37
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml27
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml27
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml27
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml27
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml27
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml27
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml29
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml29
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLog.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/dagger/TvPipModule.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java115
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java117
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java30
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java6
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java14
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java16
-rw-r--r--services/core/java/com/android/server/am/UserController.java22
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java86
-rw-r--r--services/core/java/com/android/server/appop/TEST_MAPPING3
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java74
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java35
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java60
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java9
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java192
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java71
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java15
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java10
-rw-r--r--services/core/java/com/android/server/pm/ApkChecksums.java28
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java52
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java82
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java14
-rw-r--r--services/core/java/com/android/server/pm/TEST_MAPPING9
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java101
-rw-r--r--services/core/java/com/android/server/pm/permission/TEST_MAPPING17
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java25
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java7
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java216
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java348
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java113
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java309
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java5
-rw-r--r--services/core/java/com/android/server/vr/Vr2dDisplay.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java47
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java38
-rw-r--r--services/core/java/com/android/server/wm/EventLogTags.logtags2
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java38
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java21
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java5
-rw-r--r--services/core/java/com/android/server/wm/Task.java13
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java32
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java54
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp31
-rw-r--r--services/incremental/BinderIncrementalService.cpp12
-rw-r--r--services/incremental/BinderIncrementalService.h4
-rw-r--r--services/incremental/IncrementalService.cpp106
-rw-r--r--services/incremental/IncrementalService.h7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java108
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java38
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java48
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java39
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java4
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java18
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java179
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java1274
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java267
-rw-r--r--telephony/api/system-current.txt33
-rw-r--r--telephony/java/android/telephony/CallForwardingInfo.java105
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java267
-rw-r--r--telephony/java/android/telephony/gsm/GsmCellLocation.java2
-rw-r--r--telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl25
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl76
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java22
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java35
-rw-r--r--wifi/api/system-current.txt1
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java21
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java26
-rw-r--r--wifi/tests/src/android/net/wifi/ScanResultTest.java7
451 files changed, 10559 insertions, 4383 deletions
diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp
index 4f6c21af9281..79176ff993c4 100644
--- a/apct-tests/perftests/autofill/Android.bp
+++ b/apct-tests/perftests/autofill/Android.bp
@@ -20,6 +20,7 @@ android_test {
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
+ "compatibility-device-util-axt",
"collector-device-lib",
],
platform_apis: true,
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
index 8f8fc29ee3c4..d97b5003b252 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package android.view.autofill;
@@ -28,10 +28,10 @@ import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
-import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
+import org.junit.rules.RuleChain;
/**
* Base class for all autofill tests.
@@ -43,12 +43,16 @@ public abstract class AbstractAutofillPerfTestCase {
new SettingsStateKeeperRule(InstrumentationRegistry.getTargetContext(),
Settings.Secure.AUTOFILL_SERVICE);
- @Rule
- public ActivityTestRule<PerfTestActivity> mActivityRule =
+ protected final AutofillTestWatcher mTestWatcher = MyAutofillService.getTestWatcher();
+ protected ActivityTestRule<PerfTestActivity> mActivityRule =
new ActivityTestRule<>(PerfTestActivity.class);
+ protected PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@Rule
- public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ public final RuleChain mAllRules = RuleChain
+ .outerRule(mTestWatcher)
+ .around(mPerfStatusReporter)
+ .around(mActivityRule);
private final int mLayoutId;
@@ -72,20 +76,6 @@ public abstract class AbstractAutofillPerfTestCase {
});
}
- @Before
- public void enableService() {
- MyAutofillService.resetStaticState();
- MyAutofillService.setEnabled(true);
- }
-
- @After
- public void disableService() {
- // Must disable service so calls are ignored in case of errors during the test case;
- // otherwise, other tests will fail because these calls are made in the UI thread (as both
- // the service, the tests, and the app run in the same process).
- MyAutofillService.setEnabled(false);
- }
-
/**
* Initializes the {@link PerfTestActivity} after it was launched.
*/
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/AutofillTestWatcher.java b/apct-tests/perftests/autofill/src/android/view/autofill/AutofillTestWatcher.java
new file mode 100644
index 000000000000..f1f812ddf1c7
--- /dev/null
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/AutofillTestWatcher.java
@@ -0,0 +1,133 @@
+/*
+ * 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 android.view.autofill;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Custom {@link TestWatcher} that does the setup and reset tasks for the tests.
+ */
+final class AutofillTestWatcher extends TestWatcher {
+
+ private static final String TAG = "AutofillTestWatcher";
+ private static final long GENERIC_TIMEOUT_MS = 10_000;
+
+ private static ServiceWatcher sServiceWatcher;
+
+ private String mOriginalLogLevel;
+
+ @Override
+ protected void starting(Description description) {
+ super.starting(description);
+
+ enableVerboseLog();
+ MyAutofillService.resetStaticState();
+ MyAutofillService.setEnabled(true);
+ setServiceWatcher();
+ }
+
+ @Override
+ protected void finished(Description description) {
+ super.finished(description);
+
+ restoreLogLevel();
+ disableService();
+ clearServiceWatcher();
+ }
+
+ void waitServiceConnect() throws InterruptedException {
+ if (sServiceWatcher != null) {
+ Log.d(TAG, "waitServiceConnect()");
+ sServiceWatcher.waitOnConnected();
+ }
+ }
+
+ private void enableService() {
+ MyAutofillService.resetStaticState();
+ MyAutofillService.setEnabled(true);
+ }
+
+ private void disableService() {
+ // Must disable service so calls are ignored in case of errors during the test case;
+ // otherwise, other tests will fail because these calls are made in the UI thread (as both
+ // the service, the tests, and the app run in the same process).
+ MyAutofillService.setEnabled(false);
+ }
+
+ private void enableVerboseLog() {
+ mOriginalLogLevel = runShellCommand("cmd autofill get log_level");
+ Log.d(TAG, "enableVerboseLog(), mOriginalLogLevel=" + mOriginalLogLevel);
+ if (!mOriginalLogLevel.equals("verbose")) {
+ runShellCommand("cmd autofill set log_level verbose");
+ }
+ }
+
+ private void restoreLogLevel() {
+ Log.w(TAG, "restoreLogLevel to " + mOriginalLogLevel);
+ if (!mOriginalLogLevel.equals("verbose")) {
+ runShellCommand("cmd autofill set log_level %s", mOriginalLogLevel);
+ }
+ }
+
+ private static void setServiceWatcher() {
+ if (sServiceWatcher == null) {
+ sServiceWatcher = new ServiceWatcher();
+ }
+ }
+
+ private static void clearServiceWatcher() {
+ if (sServiceWatcher != null) {
+ sServiceWatcher = null;
+ }
+ }
+
+ public static final class ServiceWatcher {
+ private final CountDownLatch mConnected = new CountDownLatch(1);
+
+ public static void onConnected() {
+ Log.i(TAG, "onConnected: sServiceWatcher=" + sServiceWatcher);
+
+ sServiceWatcher.mConnected.countDown();
+ }
+
+ @NonNull
+ public void waitOnConnected() throws InterruptedException {
+ await(mConnected, "not connected");
+ }
+
+ private void await(@NonNull CountDownLatch latch, @NonNull String fmt,
+ @Nullable Object... args)
+ throws InterruptedException {
+ final boolean called = latch.await(GENERIC_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ if (!called) {
+ throw new IllegalStateException(String.format(fmt, args)
+ + " in " + GENERIC_TIMEOUT_MS + "ms");
+ }
+ }
+ }
+}
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
index 5f52dc782422..99b2590e4049 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package android.view.autofill;
@@ -57,13 +57,13 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
public void testFocus_noService() throws Throwable {
resetService();
- mActivityRule.runOnUiThread(() -> {
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mActivityRule.runOnUiThread(() -> {
mUsername.requestFocus();
mPassword.requestFocus();
- }
- });
+ });
+ }
}
/**
@@ -82,13 +82,13 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
// Then focus on password so loop start with focus away from username
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
- mActivityRule.runOnUiThread(() -> {
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mActivityRule.runOnUiThread(() -> {
mUsername.requestFocus();
mPassword.requestFocus();
- }
- });
+ });
+ }
}
/**
@@ -252,18 +252,18 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
// outside the loop
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
if (waitForService) {
+ mTestWatcher.waitServiceConnect();
MyAutofillService.getLastFillRequest();
}
- mActivityRule.runOnUiThread(() -> {
-
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ mActivityRule.runOnUiThread(() -> {
mUsername.setText("");
mUsername.setText("a");
mPassword.setText("");
mPassword.setText("x");
- }
- });
+ });
+ }
}
// TODO(b/162216576): fix fail test and re-enable it
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/MyAutofillService.java b/apct-tests/perftests/autofill/src/android/view/autofill/MyAutofillService.java
index 7060233fc80f..77c1b85b10ab 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/MyAutofillService.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/MyAutofillService.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package android.view.autofill;
@@ -28,12 +28,9 @@ import android.util.Pair;
import android.widget.RemoteViews;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.perftests.autofill.R;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -44,7 +41,7 @@ import java.util.concurrent.TimeUnit;
public class MyAutofillService extends AutofillService {
private static final String TAG = "MyAutofillService";
- private static final int TIMEOUT_MS = 5000;
+ private static final int TIMEOUT_MS = 5_000;
private static final String PACKAGE_NAME = "com.android.perftests.autofill";
static final String COMPONENT_NAME = PACKAGE_NAME + "/android.view.autofill.MyAutofillService";
@@ -56,6 +53,14 @@ public class MyAutofillService extends AutofillService {
private static boolean sEnabled;
/**
+ * Returns the TestWatcher that was used for the testing.
+ */
+ @NonNull
+ public static AutofillTestWatcher getTestWatcher() {
+ return new AutofillTestWatcher();
+ }
+
+ /**
* Resets the static state associated with the service.
*/
static void resetStaticState() {
@@ -93,6 +98,11 @@ public class MyAutofillService extends AutofillService {
}
@Override
+ public void onConnected() {
+ AutofillTestWatcher.ServiceWatcher.onConnected();
+ }
+
+ @Override
public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal,
FillCallback callback) {
try {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index a1be7cb9f7fb..05910a5b171e 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -26,6 +26,7 @@ import static android.app.AlarmManager.RTC_WAKEUP;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.os.UserHandle.USER_SYSTEM;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManagerInternal;
@@ -39,12 +40,10 @@ import android.app.PendingIntent;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManagerInternal;
-import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
@@ -68,6 +67,7 @@ import android.os.ThreadLocalWorkSource;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.system.Os;
import android.text.TextUtils;
@@ -76,7 +76,6 @@ import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
-import android.util.KeyValueListParser;
import android.util.Log;
import android.util.LongArrayQueue;
import android.util.MutableBoolean;
@@ -102,6 +101,7 @@ import com.android.server.AppStateTrackerImpl;
import com.android.server.AppStateTrackerImpl.Listener;
import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -252,7 +252,7 @@ public class AlarmManagerService extends SystemService {
final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
interface Stats {
- int REORDER_ALARMS_FOR_STANDBY = 1;
+ int REORDER_ALARMS_FOR_STANDBY = 0;
}
private final StatLogger mStatLogger = new StatLogger("Alarm manager stats", new String[]{
@@ -374,7 +374,7 @@ public class AlarmManagerService extends SystemService {
* holding the AlarmManagerService.mLock lock.
*/
@VisibleForTesting
- final class Constants extends ContentObserver {
+ final class Constants implements DeviceConfig.OnPropertiesChangedListener {
// Key names stored in the settings value.
@VisibleForTesting
static final String KEY_MIN_FUTURITY = "min_futurity";
@@ -394,17 +394,19 @@ public class AlarmManagerService extends SystemService {
@VisibleForTesting
static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
+ private static final String KEY_PREFIX_STANDBY_QUOTA = "standby_quota_";
@VisibleForTesting
final String[] KEYS_APP_STANDBY_QUOTAS = {
- "standby_active_quota",
- "standby_working_quota",
- "standby_frequent_quota",
- "standby_rare_quota",
- "standby_never_quota",
+ KEY_PREFIX_STANDBY_QUOTA + "active",
+ KEY_PREFIX_STANDBY_QUOTA + "working",
+ KEY_PREFIX_STANDBY_QUOTA + "frequent",
+ KEY_PREFIX_STANDBY_QUOTA + "rare",
+ KEY_PREFIX_STANDBY_QUOTA + "never",
};
// Not putting this in the KEYS_APP_STANDBY_QUOTAS array because this uses a different
// window size.
- private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA = "standby_restricted_quota";
+ private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA =
+ KEY_PREFIX_STANDBY_QUOTA + "restricted";
private static final String KEY_APP_STANDBY_RESTRICTED_WINDOW =
"app_standby_restricted_window";
@@ -458,20 +460,18 @@ public class AlarmManagerService extends SystemService {
public int APP_STANDBY_RESTRICTED_QUOTA = DEFAULT_APP_STANDBY_RESTRICTED_QUOTA;
public long APP_STANDBY_RESTRICTED_WINDOW = DEFAULT_APP_STANDBY_RESTRICTED_WINDOW;
- private ContentResolver mResolver;
- private final KeyValueListParser mParser = new KeyValueListParser(',');
private long mLastAllowWhileIdleWhitelistDuration = -1;
- public Constants(Handler handler) {
- super(handler);
+ Constants() {
updateAllowWhileIdleWhitelistDurationLocked();
+ for (int i = 0; i < APP_STANDBY_QUOTAS.length; i++) {
+ APP_STANDBY_QUOTAS[i] = DEFAULT_APP_STANDBY_QUOTAS[i];
+ }
}
- public void start(ContentResolver resolver) {
- mResolver = resolver;
- mResolver.registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
- updateConstants();
+ public void start() {
+ mInjector.registerDeviceConfigListener(this);
+ onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER));
}
public void updateAllowWhileIdleWhitelistDurationLocked() {
@@ -484,71 +484,115 @@ public class AlarmManagerService extends SystemService {
}
@Override
- public void onChange(boolean selfChange, Uri uri) {
- updateConstants();
- }
-
- private void updateConstants() {
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ boolean standbyQuotaUpdated = false;
synchronized (mLock) {
- try {
- mParser.setString(Settings.Global.getString(mResolver,
- Settings.Global.ALARM_MANAGER_CONSTANTS));
- } catch (IllegalArgumentException e) {
- // Failed to parse the settings string, log this and move on
- // with defaults.
- Slog.e(TAG, "Bad alarm manager settings", e);
- }
-
- MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
- MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
- MAX_INTERVAL = mParser.getLong(KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
- ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
- DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
- ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
- DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
- ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
- KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
- DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
- LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
- DEFAULT_LISTENER_TIMEOUT);
-
- APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW,
- DEFAULT_APP_STANDBY_WINDOW);
- if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
- Slog.w(TAG, "Cannot exceed the app_standby_window size of "
- + DEFAULT_APP_STANDBY_WINDOW);
- APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
- } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
- // Not recommended outside of testing.
- Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
- }
+ for (String name : properties.getKeyset()) {
+ if (name == null) {
+ continue;
+ }
- APP_STANDBY_QUOTAS[ACTIVE_INDEX] = mParser.getInt(
- KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX],
- DEFAULT_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
- for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
- APP_STANDBY_QUOTAS[i] = mParser.getInt(KEYS_APP_STANDBY_QUOTAS[i],
- Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
+ switch (name) {
+ case KEY_MIN_FUTURITY:
+ MIN_FUTURITY = properties.getLong(
+ KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
+ break;
+ case KEY_MIN_INTERVAL:
+ MIN_INTERVAL = properties.getLong(
+ KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
+ break;
+ case KEY_MAX_INTERVAL:
+ MAX_INTERVAL = properties.getLong(
+ KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
+ break;
+ case KEY_ALLOW_WHILE_IDLE_SHORT_TIME:
+ ALLOW_WHILE_IDLE_SHORT_TIME = properties.getLong(
+ KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
+ DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
+ break;
+ case KEY_ALLOW_WHILE_IDLE_LONG_TIME:
+ ALLOW_WHILE_IDLE_LONG_TIME = properties.getLong(
+ KEY_ALLOW_WHILE_IDLE_LONG_TIME,
+ DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
+ break;
+ case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
+ ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
+ KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
+ DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
+ updateAllowWhileIdleWhitelistDurationLocked();
+ break;
+ case KEY_LISTENER_TIMEOUT:
+ LISTENER_TIMEOUT = properties.getLong(
+ KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT);
+ break;
+ case KEY_MAX_ALARMS_PER_UID:
+ MAX_ALARMS_PER_UID = properties.getInt(
+ KEY_MAX_ALARMS_PER_UID, DEFAULT_MAX_ALARMS_PER_UID);
+ if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
+ Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
+ + DEFAULT_MAX_ALARMS_PER_UID);
+ MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
+ }
+ break;
+ case KEY_APP_STANDBY_WINDOW:
+ case KEY_APP_STANDBY_RESTRICTED_WINDOW:
+ updateStandbyWindowsLocked();
+ break;
+ default:
+ if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
+ // The quotas need to be updated in order, so we can't just rely
+ // on the property iteration order.
+ updateStandbyQuotasLocked();
+ standbyQuotaUpdated = true;
+ }
+ break;
+ }
}
+ }
+ }
- APP_STANDBY_RESTRICTED_QUOTA = Math.max(1,
- mParser.getInt(KEY_APP_STANDBY_RESTRICTED_QUOTA,
- DEFAULT_APP_STANDBY_RESTRICTED_QUOTA));
+ private void updateStandbyQuotasLocked() {
+ // The bucket quotas need to be read as an atomic unit but the properties passed to
+ // onPropertiesChanged may only have one key populated at a time.
+ final DeviceConfig.Properties properties = DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_ALARM_MANAGER, KEYS_APP_STANDBY_QUOTAS);
- APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
- mParser.getLong(KEY_APP_STANDBY_RESTRICTED_WINDOW,
- DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
+ APP_STANDBY_QUOTAS[ACTIVE_INDEX] = properties.getInt(
+ KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX],
+ DEFAULT_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
+ for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
+ APP_STANDBY_QUOTAS[i] = properties.getInt(
+ KEYS_APP_STANDBY_QUOTAS[i],
+ Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
+ }
- MAX_ALARMS_PER_UID = mParser.getInt(KEY_MAX_ALARMS_PER_UID,
- DEFAULT_MAX_ALARMS_PER_UID);
- if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
- Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
- + DEFAULT_MAX_ALARMS_PER_UID);
- MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
- }
+ APP_STANDBY_RESTRICTED_QUOTA = Math.max(1,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_ALARM_MANAGER,
+ KEY_APP_STANDBY_RESTRICTED_QUOTA,
+ DEFAULT_APP_STANDBY_RESTRICTED_QUOTA));
+ }
- updateAllowWhileIdleWhitelistDurationLocked();
+ private void updateStandbyWindowsLocked() {
+ // The bucket windows need to be read as an atomic unit but the properties passed to
+ // onPropertiesChanged may only have one key populated at a time.
+ final DeviceConfig.Properties properties = DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_ALARM_MANAGER,
+ KEY_APP_STANDBY_WINDOW, KEY_APP_STANDBY_RESTRICTED_WINDOW);
+ APP_STANDBY_WINDOW = properties.getLong(
+ KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW);
+ if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
+ Slog.w(TAG, "Cannot exceed the app_standby_window size of "
+ + DEFAULT_APP_STANDBY_WINDOW);
+ APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
+ } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
+ // Not recommended outside of testing.
+ Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
}
+
+ APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
+ properties.getLong(
+ KEY_APP_STANDBY_RESTRICTED_WINDOW,
+ DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
}
void dump(PrintWriter pw, String prefix) {
@@ -1199,7 +1243,7 @@ public class AlarmManagerService extends SystemService {
synchronized (mLock) {
mHandler = new AlarmHandler();
- mConstants = new Constants(mHandler);
+ mConstants = new Constants();
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
mNextWakeup = mNextNonWakeup = 0;
@@ -1284,7 +1328,7 @@ public class AlarmManagerService extends SystemService {
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
synchronized (mLock) {
- mConstants.start(getContext().getContentResolver());
+ mConstants.start();
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mLocalDeviceIdleController =
LocalServices.getService(DeviceIdleInternal.class);
@@ -3382,6 +3426,11 @@ public class AlarmManagerService extends SystemService {
ClockReceiver getClockReceiver(AlarmManagerService service) {
return service.new ClockReceiver();
}
+
+ void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) {
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ALARM_MANAGER,
+ JobSchedulerBackgroundThread.getExecutor(), listener);
+ }
}
private class AlarmThread extends Thread {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
index a08c22213c1f..91c0c0579c69 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
@@ -46,7 +46,7 @@ public class BatchingAlarmStore implements AlarmStore {
private AlarmClockRemovalListener mAlarmClockRemovalListener;
interface Stats {
- int REBATCH_ALL_ALARMS = 1;
+ int REBATCH_ALL_ALARMS = 0;
}
final StatLogger mStatLogger = new StatLogger("Alarm store stats", new String[]{
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
index b47a210cbed8..47ebf32fa875 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ComponentController.java
@@ -77,6 +77,9 @@ public class ComponentController extends StateController {
}
};
+ private final SparseArrayMap<ComponentName, ServiceInfo> mServiceInfoCache =
+ new SparseArrayMap<>();
+
private final ComponentStateUpdateFunctor mComponentStateUpdateFunctor =
new ComponentStateUpdateFunctor();
@@ -98,40 +101,33 @@ public class ComponentController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- updateComponentEnabledStateLocked(jobStatus, null);
+ updateComponentEnabledStateLocked(jobStatus);
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
boolean forUpdate) {
-
}
@Nullable
- private ServiceInfo getServiceInfo(JobStatus jobStatus,
- @Nullable SparseArrayMap<ComponentName, ServiceInfo> cache) {
- final ComponentName cn = jobStatus.getServiceComponent();
- ServiceInfo si = null;
- if (cache != null) {
- si = cache.get(jobStatus.getUserId(), cn);
- }
+ private ServiceInfo getServiceInfo(JobStatus jobStatus) {
+ final ComponentName service = jobStatus.getServiceComponent();
+ final int userId = jobStatus.getUserId();
+ ServiceInfo si = mServiceInfoCache.get(userId, service);
if (si == null) {
try {
si = AppGlobals.getPackageManager().getServiceInfo(
- cn, PackageManager.MATCH_DIRECT_BOOT_AUTO, jobStatus.getUserId());
+ service, PackageManager.MATCH_DIRECT_BOOT_AUTO, userId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
- if (cache != null) {
- cache.add(jobStatus.getUserId(), cn, si);
- }
+ mServiceInfoCache.add(userId, service, si);
}
return si;
}
- private boolean updateComponentEnabledStateLocked(JobStatus jobStatus,
- @Nullable SparseArrayMap<ComponentName, ServiceInfo> cache) {
- final ServiceInfo service = getServiceInfo(jobStatus, cache);
+ private boolean updateComponentEnabledStateLocked(JobStatus jobStatus) {
+ final ServiceInfo service = getServiceInfo(jobStatus);
if (DEBUG && service == null) {
Slog.v(TAG, jobStatus.toShortString() + " component not present");
@@ -142,40 +138,51 @@ public class ComponentController extends StateController {
}
private void updateComponentStateForPackage(final String pkg) {
- updateComponentStates(
- jobStatus -> jobStatus.getServiceComponent().getPackageName().equals(pkg));
+ synchronized (mLock) {
+ for (int u = mServiceInfoCache.numMaps() - 1; u >= 0; --u) {
+ final int userId = mServiceInfoCache.keyAt(u);
+
+ for (int c = mServiceInfoCache.numElementsForKey(userId) - 1; c >= 0; --c) {
+ final ComponentName cn = mServiceInfoCache.keyAt(u, c);
+ if (cn.getPackageName().equals(pkg)) {
+ mServiceInfoCache.delete(userId, cn);
+ }
+ }
+ }
+ updateComponentStatesLocked(
+ jobStatus -> jobStatus.getServiceComponent().getPackageName().equals(pkg));
+ }
}
private void updateComponentStateForUser(final int userId) {
- updateComponentStates(jobStatus -> {
- // Using user ID instead of source user ID because the service will run under the
- // user ID, not source user ID.
- return jobStatus.getUserId() == userId;
- });
+ synchronized (mLock) {
+ mServiceInfoCache.delete(userId);
+ updateComponentStatesLocked(jobStatus -> {
+ // Using user ID instead of source user ID because the service will run under the
+ // user ID, not source user ID.
+ return jobStatus.getUserId() == userId;
+ });
+ }
}
- private void updateComponentStates(@NonNull Predicate<JobStatus> filter) {
- synchronized (mLock) {
- mComponentStateUpdateFunctor.reset();
- mService.getJobStore().forEachJob(filter, mComponentStateUpdateFunctor);
- if (mComponentStateUpdateFunctor.mChanged) {
- mStateChangedListener.onControllerStateChanged();
- }
+ private void updateComponentStatesLocked(@NonNull Predicate<JobStatus> filter) {
+ mComponentStateUpdateFunctor.reset();
+ mService.getJobStore().forEachJob(filter, mComponentStateUpdateFunctor);
+ if (mComponentStateUpdateFunctor.mChanged) {
+ mStateChangedListener.onControllerStateChanged();
}
}
final class ComponentStateUpdateFunctor implements Consumer<JobStatus> {
boolean mChanged;
- final SparseArrayMap<ComponentName, ServiceInfo> mTempCache = new SparseArrayMap<>();
@Override
public void accept(JobStatus jobStatus) {
- mChanged |= updateComponentEnabledStateLocked(jobStatus, mTempCache);
+ mChanged |= updateComponentEnabledStateLocked(jobStatus);
}
private void reset() {
mChanged = false;
- mTempCache.clear();
}
}
diff --git a/api/current.txt b/api/current.txt
index 04c28176db7b..4590325cb771 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11359,6 +11359,7 @@ package android.content.pm {
field public static final int CONFIG_COLOR_MODE = 16384; // 0x4000
field public static final int CONFIG_DENSITY = 4096; // 0x1000
field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
+ field public static final int CONFIG_FORCE_BOLD_TEXT = 268435456; // 0x10000000
field public static final int CONFIG_KEYBOARD = 16; // 0x10
field public static final int CONFIG_KEYBOARD_HIDDEN = 32; // 0x20
field public static final int CONFIG_LAYOUT_DIRECTION = 8192; // 0x2000
@@ -11451,6 +11452,7 @@ package android.content.pm {
method public int describeContents();
method public int getKind();
method @Nullable public java.security.cert.Certificate getSourceCertificate() throws java.security.cert.CertificateException;
+ method @Nullable public String getSourcePackageName();
method @Nullable public String getSplitName();
method @NonNull public byte[] getValue();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -11559,6 +11561,7 @@ package android.content.pm {
}
public final class Checksum implements android.os.Parcelable {
+ ctor public Checksum(int, @NonNull byte[]);
method public int describeContents();
method public int getKind();
method @NonNull public byte[] getValue();
@@ -11566,9 +11569,9 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Checksum> CREATOR;
field public static final int PARTIAL_MERKLE_ROOT_1M_SHA256 = 32; // 0x20
field public static final int PARTIAL_MERKLE_ROOT_1M_SHA512 = 64; // 0x40
- field public static final int WHOLE_MD5 = 2; // 0x2
+ field @Deprecated public static final int WHOLE_MD5 = 2; // 0x2
field public static final int WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
- field public static final int WHOLE_SHA1 = 4; // 0x4
+ field @Deprecated public static final int WHOLE_SHA1 = 4; // 0x4
field public static final int WHOLE_SHA256 = 8; // 0x8
field public static final int WHOLE_SHA512 = 16; // 0x10
}
@@ -11864,7 +11867,7 @@ package android.content.pm {
public static class PackageInstaller.Session implements java.io.Closeable {
method public void abandon();
- method public void addChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>) throws java.io.IOException;
+ method @Deprecated public void addChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>) throws java.io.IOException;
method public void addChildSessionId(int);
method public void close();
method public void commit(@NonNull android.content.IntentSender);
@@ -12680,6 +12683,9 @@ package android.content.res {
field public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
+ field public static final int FORCE_BOLD_TEXT_NO = 1; // 0x1
+ field public static final int FORCE_BOLD_TEXT_UNDEFINED = 0; // 0x0
+ field public static final int FORCE_BOLD_TEXT_YES = 2; // 0x2
field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
field public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
field public static final int HARDKEYBOARDHIDDEN_YES = 2; // 0x2
@@ -12746,6 +12752,7 @@ package android.content.res {
field public int colorMode;
field public int densityDpi;
field public float fontScale;
+ field public int forceBoldText;
field public int hardKeyboardHidden;
field public int keyboard;
field public int keyboardHidden;
@@ -24887,6 +24894,7 @@ package android.media {
}
public static final class DrmInitData.SchemeInitData {
+ ctor public DrmInitData.SchemeInitData(@NonNull java.util.UUID, @NonNull String, @NonNull byte[]);
field @NonNull public static final java.util.UUID UUID_NIL;
field public final byte[] data;
field public final String mimeType;
@@ -44286,54 +44294,8 @@ package android.service.textservice {
package android.service.voice {
- public class AlwaysOnHotwordDetector {
- method public android.content.Intent createEnrollIntent();
- method public android.content.Intent createReEnrollIntent();
- method public android.content.Intent createUnEnrollIntent();
- method public int getParameter(int);
- method public int getSupportedAudioCapabilities();
- method public int getSupportedRecognitionModes();
- method @Nullable public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
- method public int setParameter(int, int);
- method public boolean startRecognition(int);
- method public boolean stopRecognition();
- field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
- field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
- field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
- field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
- field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
- field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
- field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
- field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
- field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
- field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
- field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
- field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
- field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
- }
-
- public abstract static class AlwaysOnHotwordDetector.Callback {
- ctor public AlwaysOnHotwordDetector.Callback();
- method public abstract void onAvailabilityChanged(int);
- method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
- method public abstract void onError();
- method public abstract void onRecognitionPaused();
- method public abstract void onRecognitionResumed();
- }
-
- public static class AlwaysOnHotwordDetector.EventPayload {
- method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
- method @Nullable public byte[] getTriggerAudio();
- }
-
- public static final class AlwaysOnHotwordDetector.ModelParamRange {
- method public int getEnd();
- method public int getStart();
- }
-
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
- method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method public int getDisabledShowContext();
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 50d68db56a28..ab8944277e9a 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -153,6 +153,7 @@ package android.os {
package android.provider {
public final class DeviceConfig {
+ field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 65fe85bdd727..c4f9067b507d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7248,6 +7248,7 @@ package android.net.wifi {
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001; // 0x3e9
field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
field @Deprecated public boolean allowAutojoin;
field @Deprecated public int carrierId;
@@ -10272,7 +10273,53 @@ package android.service.trust {
package android.service.voice {
+ public class AlwaysOnHotwordDetector {
+ method @Nullable public android.content.Intent createEnrollIntent();
+ method @Nullable public android.content.Intent createReEnrollIntent();
+ method @Nullable public android.content.Intent createUnEnrollIntent();
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int);
+ method public int getSupportedAudioCapabilities();
+ method public int getSupportedRecognitionModes();
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition();
+ field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
+ field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
+ field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
+ field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
+ field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
+ field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
+ field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
+ field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
+ field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
+ field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
+ field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
+ field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
+ field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
+ }
+
+ public abstract static class AlwaysOnHotwordDetector.Callback {
+ ctor public AlwaysOnHotwordDetector.Callback();
+ method public abstract void onAvailabilityChanged(int);
+ method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
+ method public abstract void onError();
+ method public abstract void onRecognitionPaused();
+ method public abstract void onRecognitionResumed();
+ }
+
+ public static class AlwaysOnHotwordDetector.EventPayload {
+ method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
+ method @Nullable public byte[] getTriggerAudio();
+ }
+
+ public static final class AlwaysOnHotwordDetector.ModelParamRange {
+ method public int getEnd();
+ method public int getStart();
+ }
+
public class VoiceInteractionService extends android.app.Service {
+ method @NonNull public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
}
@@ -10663,6 +10710,26 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
+ public final class CallForwardingInfo implements android.os.Parcelable {
+ ctor public CallForwardingInfo(boolean, int, @Nullable String, int);
+ method public int describeContents();
+ method @Nullable public String getNumber();
+ method public int getReason();
+ method public int getTimeoutSeconds();
+ method public boolean isEnabled();
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
+ field public static final int ERROR_FDN_CHECK_FAILURE = 2; // 0x2
+ field public static final int ERROR_NOT_SUPPORTED = 3; // 0x3
+ field public static final int ERROR_UNKNOWN = 1; // 0x1
+ field public static final int REASON_ALL = 4; // 0x4
+ field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int REASON_BUSY = 1; // 0x1
+ field public static final int REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int REASON_NO_REPLY = 2; // 0x2
+ field public static final int REASON_UNCONDITIONAL = 0; // 0x0
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -11324,6 +11391,8 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -11400,6 +11469,8 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingStatus(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -11437,6 +11508,10 @@ package android.telephony {
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
+ field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
+ field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
+ field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -11491,6 +11566,11 @@ package android.telephony {
field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
}
+ public static interface TelephonyManager.CallForwardingInfoCallback {
+ method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo);
+ method public void onError(int);
+ }
+
public final class UiccAccessRule implements android.os.Parcelable {
ctor public UiccAccessRule(byte[], @Nullable String, long);
method public int describeContents();
diff --git a/api/test-current.txt b/api/test-current.txt
index 7a7cdd18e50d..5082c57cd221 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17,6 +17,7 @@ package android {
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
field public static final String NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
+ field public static final String OVERRIDE_DISPLAY_MODE_REQUESTS = "android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
@@ -1313,6 +1314,8 @@ package android.hardware.display {
method public android.graphics.Point getStableDisplaySize();
method public boolean isMinimalPostProcessingRequested(int);
method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
+ method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
+ method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200
field public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1024; // 0x400
}
@@ -3291,6 +3294,7 @@ package android.provider {
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties) throws android.provider.DeviceConfig.BadConfigException;
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
+ field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
field public static final String NAMESPACE_ANDROID = "android";
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_BIOMETRICS = "biometrics";
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 3bf4e636be89..5a6b8cf334eb 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -68,9 +68,9 @@ public:
// index: the new index of this tracker in allConditionProtos and allConditionTrackers.
// allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
// need to call onConfigUpdated() on child conditions)
- // [atomMatchingTrackerMap]: map of atom matcher id to index after the config update
- // [conditionTrackerMap]: map of condition tracker id to index after the config update.
- // returns whether or not the update is successful
+ // atomMatchingTrackerMap: map of atom matcher id to index after the config update.
+ // conditionTrackerMap: map of condition tracker id to index after the config update.
+ // returns whether or not the update is successful.
virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index dfe4559b05fb..ca302c0e71fb 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -18,12 +18,14 @@
#include "Log.h"
#include "EventMetricProducer.h"
-#include "stats_util.h"
-#include "stats_log_util.h"
#include <limits.h>
#include <stdlib.h>
+#include "metrics/parsing_utils/metrics_manager_util.h"
+#include "stats_log_util.h"
+#include "stats_util.h"
+
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
using android::util::FIELD_TYPE_FLOAT;
@@ -82,6 +84,47 @@ EventMetricProducer::~EventMetricProducer() {
VLOG("~EventMetricProducer() called");
}
+bool EventMetricProducer::onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
+ trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ return false;
+ }
+
+ const EventMetric& metric = config.event_metric(configIndex);
+ int trackerIndex;
+ // Update appropriate indices, specifically mConditionIndex and MetricsManager maps.
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
+ return false;
+ }
+
+ if (metric.has_condition() &&
+ !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, mConditionTrackerIndex,
+ conditionToMetricMap)) {
+ return false;
+ }
+ return true;
+}
+
void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
mProto->clear();
StatsdStats::getInstance().noteBucketDropped(mMetricId);
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index e828dddcbb18..3347d7b6aab5 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -69,6 +69,22 @@ private:
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
+ bool onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation) override;
+
void dropDataLocked(const int64_t dropTimeNs) override;
// Internal function to calculate the current used bytes.
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index c1c1d20f00e2..95a7d40ea9a9 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -20,6 +20,7 @@
#include "MetricProducer.h"
#include "../guardrail/StatsdStats.h"
+#include "metrics/parsing_utils/metrics_manager_util.h"
#include "state/StateTracker.h"
using android::util::FIELD_COUNT_REPEATED;
@@ -72,6 +73,37 @@ MetricProducer::MetricProducer(
mStateGroupMap(stateGroupMap) {
}
+bool MetricProducer::onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ sp<ConditionWizard> tmpWizard = mWizard;
+ mWizard = wizard;
+
+ unordered_map<int, shared_ptr<Activation>> newEventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> newEventDeactivationMap;
+ if (!handleMetricActivationOnConfigUpdate(
+ config, mMetricId, metricIndex, metricToActivationMap, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, mEventActivationMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, newEventActivationMap,
+ newEventDeactivationMap)) {
+ return false;
+ }
+ mEventActivationMap = newEventActivationMap;
+ mEventDeactivationMap = newEventDeactivationMap;
+ return true;
+}
+
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
if (!mIsActive) {
return;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index bb590aac54d6..320b28581a38 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -26,6 +26,7 @@
#include "anomaly/AnomalyTracker.h"
#include "condition/ConditionWizard.h"
#include "config/ConfigKey.h"
+#include "matchers/EventMatcherWizard.h"
#include "matchers/matcher_util.h"
#include "packages/PackageInfoListener.h"
#include "state/StateListener.h"
@@ -151,6 +152,33 @@ public:
return conditionIndex >= 0 ? initialConditionCache[conditionIndex] : ConditionState::kTrue;
}
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This metric and all of its dependencies are guaranteed to be preserved across the update.
+ // This function also updates several maps used by metricsManager.
+ bool onConfigUpdated(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return onConfigUpdatedLocked(config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap,
+ matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ };
+
/**
* Force a partial bucket split on app upgrade
*/
@@ -209,6 +237,25 @@ public:
dumpLatency, str_set, protoOutput);
}
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This metric and all of its dependencies are guaranteed to be preserved across the update.
+ // This function also updates several maps used by metricsManager.
+ virtual bool onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
void clearPastBuckets(const int64_t dumpTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
return clearPastBucketsLocked(dumpTimeNs);
@@ -517,6 +564,9 @@ protected:
FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
FRIEND_TEST(MetricsManagerTest, TestInitialConditions);
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricActivations);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 39806890c42d..ab0d286d6b29 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -206,18 +206,33 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
vector<sp<ConditionTracker>> newConditionTrackers;
unordered_map<int64_t, int> newConditionTrackerMap;
+ map<int64_t, uint64_t> newStateProtoHashes;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int64_t, int> newMetricProducerMap;
mTagIds.clear();
+ mConditionToMetricMap.clear();
+ mTrackerToMetricMap.clear();
mTrackerToConditionMap.clear();
+ mActivationAtomTrackerToMetricMap.clear();
+ mDeactivationAtomTrackerToMetricMap.clear();
+ mMetricIndexesWithActivation.clear();
+ mNoReportMetricIds.clear();
mConfigValid = updateStatsdConfig(
mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
- mAllConditionTrackers, mConditionTrackerMap, mTagIds, newAtomMatchingTrackers,
- newAtomMatchingTrackerMap, newConditionTrackers, newConditionTrackerMap,
- mTrackerToConditionMap);
+ mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
+ mStateProtoHashes, mTagIds, newAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ newConditionTrackers, newConditionTrackerMap, newMetricProducers, newMetricProducerMap,
+ mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
+ mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
+ mMetricIndexesWithActivation, newStateProtoHashes, mNoReportMetricIds);
mAllAtomMatchingTrackers = newAtomMatchingTrackers;
mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
mAllConditionTrackers = newConditionTrackers;
mConditionTrackerMap = newConditionTrackerMap;
+ mAllMetricProducers = newMetricProducers;
+ mMetricProducerMap = newMetricProducerMap;
+ mStateProtoHashes = newStateProtoHashes;
return mConfigValid;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index bd60b6bfcb8e..5dbf16deb552 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -21,6 +21,7 @@
#include "external/StatsPullerManager.h"
#include "hash.h"
+#include "matchers/EventMatcherWizard.h"
#include "metrics_manager_util.h"
namespace android {
@@ -394,6 +395,210 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
return true;
}
+// Returns true if any matchers in the metric activation were replaced.
+bool metricActivationDepsChange(const StatsdConfig& config,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const int64_t metricId, const set<int64_t>& replacedMatchers) {
+ const auto& metricActivationIt = metricToActivationMap.find(metricId);
+ if (metricActivationIt == metricToActivationMap.end()) {
+ return false;
+ }
+ const MetricActivation& metricActivation = config.metric_activation(metricActivationIt->second);
+ for (int i = 0; i < metricActivation.event_activation_size(); i++) {
+ const EventActivation& activation = metricActivation.event_activation(i);
+ if (replacedMatchers.find(activation.atom_matcher_id()) != replacedMatchers.end()) {
+ return true;
+ }
+ if (activation.has_deactivation_atom_matcher_id()) {
+ if (replacedMatchers.find(activation.deactivation_atom_matcher_id()) !=
+ replacedMatchers.end()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool determineEventMetricUpdateStatus(const StatsdConfig& config, const EventMetric& metric,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const set<int64_t>& replacedMatchers,
+ const set<int64_t>& replacedConditions,
+ UpdateStatus& updateStatus) {
+ int64_t id = metric.id();
+ // Check if new metric
+ const auto& oldMetricProducerIt = oldMetricProducerMap.find(id);
+ if (oldMetricProducerIt == oldMetricProducerMap.end()) {
+ updateStatus = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing metric, check if it has changed.
+ uint64_t metricHash;
+ if (!getMetricProtoHash(config, metric, id, metricToActivationMap, metricHash)) {
+ return false;
+ }
+ const sp<MetricProducer> oldMetricProducer = oldMetricProducers[oldMetricProducerIt->second];
+ if (oldMetricProducer->getMetricType() != METRIC_TYPE_EVENT ||
+ oldMetricProducer->getProtoHash() != metricHash) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+
+ // Metric type and definition are the same. Need to check dependencies to see if they changed.
+ if (replacedMatchers.find(metric.what()) != replacedMatchers.end()) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+
+ if (metric.has_condition()) {
+ if (replacedConditions.find(metric.condition()) != replacedConditions.end()) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+ }
+
+ if (metricActivationDepsChange(config, metricToActivationMap, id, replacedMatchers)) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+
+ for (const auto& metricConditionLink : metric.links()) {
+ if (replacedConditions.find(metricConditionLink.condition()) != replacedConditions.end()) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ updateStatus = UPDATE_PRESERVE;
+ return true;
+}
+
+bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const set<int64_t>& replacedConditions,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const vector<ConditionState>& initialConditionCache,
+ const unordered_map<int64_t, int>& stateAtomIdMap,
+ const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ const set<int64_t>& replacedStates,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ unordered_map<int64_t, int>& newMetricProducerMap,
+ vector<sp<MetricProducer>>& newMetricProducers,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ set<int64_t>& noReportMetricIds,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
+ sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
+ const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
+ config.event_metric_size() + config.gauge_metric_size() +
+ config.value_metric_size();
+ newMetricProducers.reserve(allMetricsCount);
+
+ // Construct map from metric id to metric activation index. The map will be used to determine
+ // the metric activation corresponding to a metric.
+ unordered_map<int64_t, int> metricToActivationMap;
+ for (int i = 0; i < config.metric_activation_size(); i++) {
+ const MetricActivation& metricActivation = config.metric_activation(i);
+ int64_t metricId = metricActivation.metric_id();
+ if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
+ ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
+ return false;
+ }
+ metricToActivationMap.insert({metricId, i});
+ }
+
+ vector<UpdateStatus> metricsToUpdate(allMetricsCount, UPDATE_UNKNOWN);
+ int metricIndex = 0;
+ for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
+ newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
+ if (!determineEventMetricUpdateStatus(config, config.event_metric(i), oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions,
+ metricsToUpdate[metricIndex])) {
+ return false;
+ }
+ }
+
+ // TODO: determine update status for count, gauge, value, duration metrics.
+
+ // Now, perform the update. Must iterate the metric types in the same order
+ metricIndex = 0;
+ for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
+ const EventMetric& metric = config.event_metric(i);
+ switch (metricsToUpdate[metricIndex]) {
+ case UPDATE_PRESERVE: {
+ const auto& oldMetricProducerIt = oldMetricProducerMap.find(metric.id());
+ if (oldMetricProducerIt == oldMetricProducerMap.end()) {
+ ALOGE("Could not find Metric %lld in the previous config, but expected it "
+ "to be there",
+ (long long)metric.id());
+ return false;
+ }
+ const int oldIndex = oldMetricProducerIt->second;
+ sp<MetricProducer> producer = oldMetricProducers[oldIndex];
+ producer->onConfigUpdated(
+ config, i, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers,
+ conditionTrackerMap, wizard, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ newMetricProducers.push_back(producer);
+ break;
+ }
+ case UPDATE_REPLACE:
+ case UPDATE_NEW: {
+ sp<MetricProducer> producer = createEventMetricProducerAndUpdateMetadata(
+ key, config, timeBaseNs, metric, metricIndex, allAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
+ initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ if (producer == nullptr) {
+ return false;
+ }
+ newMetricProducers.push_back(producer);
+ break;
+ }
+ default: {
+ ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
+ (long long)metric.id());
+ return false;
+ }
+ }
+ }
+ // TODO: perform update for count, gauge, value, duration metric.
+
+ const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
+ config.whitelisted_atom_ids().end());
+ for (int i = 0; i < allMetricsCount; i++) {
+ sp<MetricProducer> producer = newMetricProducers[i];
+ // Register metrics to StateTrackers
+ for (int atomId : producer->getSlicedStateAtoms()) {
+ // Register listener for atoms that use allowed_log_sources.
+ // Using atoms allowed from any uid as a sliced state atom is not allowed.
+ // Redo this check for all metrics in case the atoms allowed from any uid changed.
+ if (atomsAllowedFromAnyUid.find(atomId) != atomsAllowedFromAnyUid.end()) {
+ return false;
+ // Preserved metrics should've already registered.`
+ } else if (metricsToUpdate[i] != UPDATE_PRESERVE) {
+ StateManager::getInstance().registerListener(atomId, producer);
+ }
+ }
+ }
+
+ return true;
+}
+
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -403,15 +608,28 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
const vector<sp<ConditionTracker>>& oldConditionTrackers,
const unordered_map<int64_t, int>& oldConditionTrackerMap,
- set<int>& allTagIds,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const map<int64_t, uint64_t>& oldStateProtoHashes, set<int>& allTagIds,
vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
vector<sp<ConditionTracker>>& newConditionTrackers,
unordered_map<int64_t, int>& newConditionTrackerMap,
- unordered_map<int, vector<int>>& trackerToConditionMap) {
+ vector<sp<MetricProducer>>& newMetricProducers,
+ unordered_map<int64_t, int>& newMetricProducerMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ unordered_map<int, vector<int>>& activationTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationTrackerToMetricMap,
+ vector<int>& metricsWithActivation,
+ map<int64_t, uint64_t>& newStateProtoHashes,
+ set<int64_t>& noReportMetricIds) {
set<int64_t> replacedMatchers;
set<int64_t> replacedConditions;
vector<ConditionState> conditionCache;
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
oldAtomMatchingTrackers, allTagIds, newAtomMatchingTrackerMap,
@@ -430,6 +648,31 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
}
VLOG("updateConditions succeeded");
+ // Share with metrics_manager_util,
+ if (!initStates(config, stateAtomIdMap, allStateGroupMaps, newStateProtoHashes)) {
+ ALOGE("initStates failed");
+ return false;
+ }
+
+ set<int64_t> replacedStates;
+ for (const auto& [stateId, stateHash] : oldStateProtoHashes) {
+ const auto& it = newStateProtoHashes.find(stateId);
+ if (it != newStateProtoHashes.end() && it->second != stateHash) {
+ replacedStates.insert(stateId);
+ }
+ }
+ if (!updateMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps,
+ replacedStates, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationTrackerToMetricMap,
+ deactivationTrackerToMetricMap, metricsWithActivation)) {
+ ALOGE("initMetricProducers failed");
+ return false;
+ }
+
return true;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
index 7ba684a65e88..1cd0ce524b31 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -22,6 +22,7 @@
#include "condition/ConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "matchers/AtomMatchingTracker.h"
+#include "metrics/MetricProducer.h"
namespace android {
namespace os {
@@ -112,7 +113,7 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
// [trackerToConditionMap]: contains the mapping from the index of an atom matcher
// to indices of condition trackers that use the matcher
// [conditionCache]: stores the current conditions for each ConditionTracker
-// [replacedConditions]: set of matcher ids that have changed and have been replaced
+// [replacedConditions]: set of condition ids that have changed and have been replaced
bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
const std::set<int64_t>& replacedMatchers,
@@ -124,6 +125,68 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
std::vector<ConditionState>& conditionCache,
std::set<int64_t>& replacedConditions);
+// Function to determine if an event metric needs to be updated. Populates updateStatus.
+// [config]: the input StatsdConfig
+// [metric]: the current metric to be updated
+// [oldMetricProducerMap]: metric id to index mapping in the existing MetricsManager
+// [oldMetricProducers]: stores the existing MetricProducers
+// [metricToActivationMap]: map from metric id to metric activation index.
+// [replacedMatchers]: set of replaced matcher ids. conditions using these matchers must be replaced
+// output:
+// [updateStatus]: update status for the metric. Will be changed from UPDATE_UNKNOWN after this call
+// Returns whether the function was successful or not.
+bool determineEventMetricUpdateStatus(const StatsdConfig& config, const EventMetric& metric,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const set<int64_t>& replacedMatchers,
+ const set<int64_t>& replacedConditions,
+ UpdateStatus& updateStatus);
+
+// Update MetricProducers.
+// input:
+// [key]: the config key that this config belongs to
+// [config]: the input config
+// [timeBaseNs]: start time base for all metrics
+// [currentTimeNs]: time of the config update
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
+// [replacedMatchers]: ids of replaced matchers. Metrics depending on these must also be replaced
+// [allAtomMatchingTrackers]: stores the sp of the atom matchers.
+// [conditionTrackerMap]: condition name to index mapping
+// [replacedConditions]: set of condition ids that have changed and have been replaced
+// [stateAtomIdMap]: contains the mapping from state ids to atom ids
+// [allStateGroupMaps]: contains the mapping from atom ids and state values to
+// state group ids for all states
+// output:
+// [allMetricProducers]: contains the list of sp to the MetricProducers created.
+// [conditionToMetricMap]: contains the mapping from condition tracker index to
+// the list of MetricProducer index
+// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
+bool updateMetrics(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const std::set<int64_t>& replacedConditions,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::vector<ConditionState>& initialConditionCache,
+ const std::unordered_map<int64_t, int>& stateAtomIdMap,
+ const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
+ const std::set<int64_t>& replacedStates,
+ const std::unordered_map<int64_t, int>& oldMetricProducerMap,
+ const std::vector<sp<MetricProducer>>& oldMetricProducers,
+ std::unordered_map<int64_t, int>& newMetricProducerMap,
+ std::vector<sp<MetricProducer>>& newMetricProducers,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::set<int64_t>& noReportMetricIds,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
// Updates the existing MetricsManager from a new StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
@@ -135,12 +198,24 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<MetricProducer>>& oldMetricProducers,
+ const std::unordered_map<int64_t, int>& oldMetricProducerMap,
+ const std::map<int64_t, uint64_t>& oldStateProtoHashes,
std::set<int>& allTagIds,
std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
std::vector<sp<ConditionTracker>>& newConditionTrackers,
std::unordered_map<int64_t, int>& newConditionTrackerMap,
- std::unordered_map<int, std::vector<int>>& trackerToConditionMap);
+ std::vector<sp<MetricProducer>>& newMetricProducers,
+ std::unordered_map<int64_t, int>& newMetricProducerMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::unordered_map<int, std::vector<int>>& activationTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation,
+ std::map<int64_t, uint64_t>& newStateProtoHashes,
+ std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 3f40c90d515a..51df7df5174e 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -61,20 +61,6 @@ bool hasLeafNode(const FieldMatcher& matcher) {
return true;
}
-bool getMetricProtoHash(const MessageLite& metric, const int64_t id, const bool hasActivation,
- const uint64_t activationHash, uint64_t& metricHash) {
- string serializedMetric;
- if (!metric.SerializeToString(&serializedMetric)) {
- ALOGE("Unable to serialize metric %lld", (long long)id);
- return false;
- }
- metricHash = Hash64(serializedMetric);
- if (hasActivation) {
- metricHash = Hash64(to_string(metricHash).append(to_string(activationHash)));
- }
- return true;
-}
-
} // namespace
sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
@@ -120,43 +106,45 @@ sp<ConditionTracker> createConditionTracker(
}
}
-bool handleMetricWithAtomMatchingTrackers(
- const int64_t what, const int metricIndex, const bool usedForDimension,
- const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap,
- unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
- auto logTrackerIt = atomMatchingTrackerMap.find(what);
- if (logTrackerIt == atomMatchingTrackerMap.end()) {
- ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
+bool getMetricProtoHash(const StatsdConfig& config, const MessageLite& metric, const int64_t id,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ uint64_t& metricHash) {
+ string serializedMetric;
+ if (!metric.SerializeToString(&serializedMetric)) {
+ ALOGE("Unable to serialize metric %lld", (long long)id);
return false;
}
- if (usedForDimension &&
- allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
- ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
- "the \"what\" can only about one atom type.",
- (long long)what);
- return false;
+ metricHash = Hash64(serializedMetric);
+
+ // Combine with activation hash, if applicable
+ const auto& metricActivationIt = metricToActivationMap.find(id);
+ if (metricActivationIt != metricToActivationMap.end()) {
+ string serializedActivation;
+ const MetricActivation& activation = config.metric_activation(metricActivationIt->second);
+ if (!activation.SerializeToString(&serializedActivation)) {
+ ALOGE("Unable to serialize metric activation for metric %lld", (long long)id);
+ return false;
+ }
+ metricHash = Hash64(to_string(metricHash).append(to_string(Hash64(serializedActivation))));
}
- logTrackerIndex = logTrackerIt->second;
- auto& metric_list = trackerToMetricMap[logTrackerIndex];
- metric_list.push_back(metricIndex);
return true;
}
-bool handlePullMetricTriggerWithAtomMatchingTrackers(
- const int64_t trigger, const int metricIndex,
+bool handleMetricWithAtomMatchingTrackers(
+ const int64_t matcherId, const int metricIndex, const bool enforceOneAtom,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& atomMatchingTrackerMap,
- unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
- auto logTrackerIt = atomMatchingTrackerMap.find(trigger);
+ unordered_map<int, vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
+ auto logTrackerIt = atomMatchingTrackerMap.find(matcherId);
if (logTrackerIt == atomMatchingTrackerMap.end()) {
- ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)trigger);
+ ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)matcherId);
return false;
}
- if (allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
- ALOGE("AtomMatcher \"%lld\" has more than one tag ids."
- "Trigger can only be one atom type.",
- (long long)trigger);
+ if (enforceOneAtom && allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
+ ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
+ "the \"what\" can only be about one atom type. trigger_event matchers can also only "
+ "be about one atom type.",
+ (long long)matcherId);
return false;
}
logTrackerIndex = logTrackerIt->second;
@@ -170,8 +158,8 @@ bool handleMetricWithConditions(
const unordered_map<int64_t, int>& conditionTrackerMap,
const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
links,
- vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
- unordered_map<int, std::vector<int>>& conditionToMetricMap) {
+ const vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
+ unordered_map<int, vector<int>>& conditionToMetricMap) {
auto condition_it = conditionTrackerMap.find(condition);
if (condition_it == conditionTrackerMap.end()) {
ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
@@ -243,31 +231,21 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
bool handleMetricActivation(
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap, bool& hasActivation,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation,
unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
- unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
- uint64_t& activationHash) {
+ unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
// Check if metric has an associated activation
auto itr = metricToActivationMap.find(metricId);
if (itr == metricToActivationMap.end()) {
- hasActivation = false;
return true;
}
- hasActivation = true;
int activationIndex = itr->second;
const MetricActivation& metricActivation = config.metric_activation(activationIndex);
- string serializedActivation;
- if (!metricActivation.SerializeToString(&serializedActivation)) {
- ALOGE("Unable to serialize metric activation for metric %lld", (long long)metricId);
- return false;
- }
- activationHash = Hash64(serializedActivation);
-
for (int i = 0; i < metricActivation.event_activation_size(); i++) {
const EventActivation& activation = metricActivation.event_activation(i);
@@ -303,6 +281,130 @@ bool handleMetricActivation(
return true;
}
+// Validates a metricActivation and populates state.
+// Fills the new event activation/deactivation maps, preserving the existing activations
+// Returns false if there are errors.
+bool handleMetricActivationOnConfigUpdate(
+ const StatsdConfig& config, const int64_t metricId, const int metricIndex,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const unordered_map<int, shared_ptr<Activation>>& oldEventActivationMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation,
+ unordered_map<int, shared_ptr<Activation>>& newEventActivationMap,
+ unordered_map<int, vector<shared_ptr<Activation>>>& newEventDeactivationMap) {
+ // Check if metric has an associated activation.
+ const auto& itr = metricToActivationMap.find(metricId);
+ if (itr == metricToActivationMap.end()) {
+ return true;
+ }
+
+ int activationIndex = itr->second;
+ const MetricActivation& metricActivation = config.metric_activation(activationIndex);
+
+ for (int i = 0; i < metricActivation.event_activation_size(); i++) {
+ const int64_t activationMatcherId = metricActivation.event_activation(i).atom_matcher_id();
+
+ const auto& newActivationIt = newAtomMatchingTrackerMap.find(activationMatcherId);
+ if (newActivationIt == newAtomMatchingTrackerMap.end()) {
+ ALOGE("Atom matcher not found in new config for event activation.");
+ return false;
+ }
+ int newActivationMatcherIndex = newActivationIt->second;
+
+ // Find the old activation struct and copy it over.
+ const auto& oldActivationIt = oldAtomMatchingTrackerMap.find(activationMatcherId);
+ if (oldActivationIt == oldAtomMatchingTrackerMap.end()) {
+ ALOGE("Atom matcher not found in existing config for event activation.");
+ return false;
+ }
+ int oldActivationMatcherIndex = oldActivationIt->second;
+ const auto& oldEventActivationIt = oldEventActivationMap.find(oldActivationMatcherIndex);
+ if (oldEventActivationIt == oldEventActivationMap.end()) {
+ ALOGE("Could not find existing event activation to update");
+ return false;
+ }
+ newEventActivationMap.emplace(newActivationMatcherIndex, oldEventActivationIt->second);
+ activationAtomTrackerToMetricMap[newActivationMatcherIndex].push_back(metricIndex);
+
+ if (metricActivation.event_activation(i).has_deactivation_atom_matcher_id()) {
+ const int64_t deactivationMatcherId =
+ metricActivation.event_activation(i).deactivation_atom_matcher_id();
+ const auto& newDeactivationIt = newAtomMatchingTrackerMap.find(deactivationMatcherId);
+ if (newDeactivationIt == newAtomMatchingTrackerMap.end()) {
+ ALOGE("Deactivation atom matcher not found in new config for event activation.");
+ return false;
+ }
+ int newDeactivationMatcherIndex = newDeactivationIt->second;
+ newEventDeactivationMap[newDeactivationMatcherIndex].push_back(
+ oldEventActivationIt->second);
+ deactivationAtomTrackerToMetricMap[newDeactivationMatcherIndex].push_back(metricIndex);
+ }
+ }
+
+ metricsWithActivation.push_back(metricIndex);
+ return true;
+}
+
+sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const EventMetric& metric, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!metric.has_id() || !metric.has_what()) {
+ ALOGW("cannot find the metric name or what in config");
+ return nullptr;
+ }
+ int trackerIndex;
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
+ return nullptr;
+ }
+
+ int conditionIndex = -1;
+ if (metric.has_condition()) {
+ if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, conditionIndex,
+ conditionToMetricMap)) {
+ return nullptr;
+ }
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ return nullptr;
+ }
+ }
+
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
+ atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ eventActivationMap, eventDeactivationMap);
+ if (!success) return nullptr;
+
+ uint64_t metricHash;
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ return nullptr;
+ }
+
+ return new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ metricHash, timeBaseNs, eventActivationMap,
+ eventDeactivationMap);
+}
+
bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
unordered_map<int64_t, int>& atomMatchingTrackerMap,
vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -492,18 +594,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
uint64_t metricHash;
- if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
return false;
}
@@ -608,18 +708,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
uint64_t metricHash;
- if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
return false;
}
@@ -637,52 +735,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int metricIndex = allMetricProducers.size();
const EventMetric& metric = config.event_metric(i);
metricMap.insert({metric.id(), metricIndex});
- if (!metric.has_id() || !metric.has_what()) {
- ALOGW("cannot find the metric name or what in config");
- return false;
- }
- int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
- return false;
- }
-
- int conditionIndex = -1;
- if (metric.has_condition()) {
- bool good = handleMetricWithConditions(
- metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
- allConditionTrackers, conditionIndex, conditionToMetricMap);
- if (!good) {
- return false;
- }
- } else {
- if (metric.links_size() > 0) {
- ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return false;
- }
- }
-
- bool hasActivation = false;
- unordered_map<int, shared_ptr<Activation>> eventActivationMap;
- unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- uint64_t activationHash;
- bool success = handleMetricActivation(
- config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
- if (!success) return false;
-
- uint64_t metricHash;
- if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ sp<MetricProducer> producer = createEventMetricProducerAndUpdateMetadata(
+ key, config, timeBaseTimeNs, metric, metricIndex, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
+ initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ if (producer == nullptr) {
return false;
}
-
- sp<MetricProducer> eventMetric = new EventMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
- timeBaseTimeNs, eventActivationMap, eventDeactivationMap);
-
- allMetricProducers.push_back(eventMetric);
+ allMetricProducers.push_back(producer);
}
// build ValueMetricProducer
@@ -759,18 +821,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
uint64_t metricHash;
- if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
return false;
}
@@ -832,9 +892,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
return false;
}
- if (!handlePullMetricTriggerWithAtomMatchingTrackers(
- metric.trigger_event(), metricIndex, allAtomMatchingTrackers,
- atomMatchingTrackerMap, trackerToMetricMap, triggerTrackerIndex)) {
+ if (!handleMetricWithAtomMatchingTrackers(
+ metric.trigger_event(), metricIndex, /*enforceOneAtom=*/true,
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap,
+ triggerTrackerIndex)) {
return false;
}
sp<AtomMatchingTracker> triggerAtomMatcher =
@@ -863,18 +924,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
uint64_t metricHash;
- if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
return false;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 4979c3051133..fdfe5cfa6491 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -30,7 +30,7 @@ namespace android {
namespace os {
namespace statsd {
-// Helper functions for creating individual config components from StatsdConfig.
+// Helper functions for creating, validating, and updating config components from StatsdConfig.
// Should only be called from metrics_manager_util and config_update_utils.
// Create a AtomMatchingTracker.
@@ -53,6 +53,61 @@ sp<ConditionTracker> createConditionTracker(
const ConfigKey& key, const Predicate& predicate, const int index,
const unordered_map<int64_t, int>& atomMatchingTrackerMap);
+// Get the hash of a metric, combining the activation if the metric has one.
+bool getMetricProtoHash(const StatsdConfig& config, const google::protobuf::MessageLite& metric,
+ const int64_t id,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ uint64_t& metricHash);
+
+// 1. Validates matcher existence
+// 2. Enforces matchers with dimensions and those used for trigger_event are about one atom
+// 3. Gets matcher index and updates tracker to metric map
+bool handleMetricWithAtomMatchingTrackers(
+ const int64_t matcherId, const int metricIndex, const bool enforceOneAtom,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex);
+
+// 1. Validates condition existence, including those in links
+// 2. Gets condition index and updates condition to metric map
+bool handleMetricWithConditions(
+ const int64_t condition, const int metricIndex,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
+ links,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap);
+
+// Validates a metricActivation and populates state.
+// Fills the new event activation/deactivation maps, preserving the existing activations.
+// Returns false if there are errors.
+bool handleMetricActivationOnConfigUpdate(
+ const StatsdConfig& config, const int64_t metricId, const int metricIndex,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const std::unordered_map<int, shared_ptr<Activation>>& oldEventActivationMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation,
+ std::unordered_map<int, shared_ptr<Activation>>& newEventActivationMap,
+ std::unordered_map<int, std::vector<shared_ptr<Activation>>>& newEventDeactivationMap);
+
+sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const EventMetric& metric, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -154,10 +209,10 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
- unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation,
+ std::vector<int>& metricsWithActivation,
std::map<int64_t, uint64_t>& stateProtoHashes,
std::set<int64_t>& noReportMetricIds);
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 843d836a2c0b..076000fab80f 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -34,6 +34,8 @@ using namespace testing;
using android::sp;
using android::os::statsd::Predicate;
using std::map;
+using std::nullopt;
+using std::optional;
using std::set;
using std::unordered_map;
using std::vector;
@@ -61,11 +63,11 @@ vector<sp<MetricProducer>> oldMetricProducers;
unordered_map<int64_t, int> oldMetricProducerMap;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
-unordered_map<int, std::vector<int>> conditionToMetricMap;
-unordered_map<int, std::vector<int>> trackerToMetricMap;
-unordered_map<int, std::vector<int>> trackerToConditionMap;
-unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
-unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+unordered_map<int, std::vector<int>> tmpConditionToMetricMap;
+unordered_map<int, std::vector<int>> tmpTrackerToMetricMap;
+unordered_map<int, std::vector<int>> tmpTrackerToConditionMap;
+unordered_map<int, std::vector<int>> tmpActivationAtomTrackerToMetricMap;
+unordered_map<int, std::vector<int>> tmpDeactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
map<int64_t, uint64_t> oldStateHashes;
@@ -86,11 +88,11 @@ public:
oldMetricProducerMap.clear();
oldAnomalyTrackers.clear();
oldAlarmTrackers.clear();
- conditionToMetricMap.clear();
- trackerToMetricMap.clear();
- trackerToConditionMap.clear();
- activationAtomTrackerToMetricMap.clear();
- deactivationAtomTrackerToMetricMap.clear();
+ tmpConditionToMetricMap.clear();
+ tmpTrackerToMetricMap.clear();
+ tmpTrackerToConditionMap.clear();
+ tmpActivationAtomTrackerToMetricMap.clear();
+ tmpDeactivationAtomTrackerToMetricMap.clear();
alertTrackerMap.clear();
metricsWithActivation.clear();
oldStateHashes.clear();
@@ -103,12 +105,22 @@ bool initConfig(const StatsdConfig& config) {
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap,
oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap,
- oldAnomalyTrackers, oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
- trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ oldAnomalyTrackers, oldAlarmTrackers, tmpConditionToMetricMap, tmpTrackerToMetricMap,
+ tmpTrackerToConditionMap, tmpActivationAtomTrackerToMetricMap,
+ tmpDeactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
oldStateHashes, noReportMetricIds);
}
+EventMetric createEventMetric(string name, int64_t what, optional<int64_t> condition) {
+ EventMetric metric;
+ metric.set_id(StringToId(name));
+ metric.set_what(what);
+ if (condition) {
+ metric.set_condition(condition.value());
+ }
+ return metric;
+}
+
} // anonymous namespace
TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -660,7 +672,6 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) {
TEST_F(ConfigUpdateTest, TestUpdateConditions) {
StatsdConfig config;
-
// Add atom matchers. These are mostly needed for initStatsdConfig
AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
int64_t matcher1Id = matcher1.id();
@@ -734,7 +745,7 @@ TEST_F(ConfigUpdateTest, TestUpdateConditions) {
set<int64_t> replacedMatchers;
replacedMatchers.insert(matcher6Id);
- // Change the condition of simple1 to true.
+ // Change the condition of simple1 to false.
ASSERT_EQ(oldConditionTrackers[0]->getConditionId(), simple1Id);
LogEvent event(/*uid=*/0, /*pid=*/0); // Empty event is fine since there are no dimensions.
// Mark the stop matcher as matched, condition should be false.
@@ -747,7 +758,7 @@ TEST_F(ConfigUpdateTest, TestUpdateConditions) {
EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse);
EXPECT_EQ(conditionChangeCache[0], true);
- // New combination matcher. Should have an initial condition of true since it is NOT(simple1).
+ // New combination predicate. Should have an initial condition of true since it is NOT(simple1).
Predicate combination4;
combination4.set_id(StringToId("COMBINATION4"));
combination4.mutable_combination()->set_operation(LogicalOperation::NOT);
@@ -888,6 +899,562 @@ TEST_F(ConfigUpdateTest, TestUpdateConditions) {
UnorderedElementsAre(simple1Index, simple2Index));
EXPECT_THAT(combinationTracker1->mSlicedChildren, IsEmpty());
}
+
+TEST_F(ConfigUpdateTest, TestEventMetricPreserve) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ unordered_map<int64_t, int> metricToActivationMap;
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestEventMetricActivationAdded) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ // Add a metric activation, which should change the proto, causing replacement.
+ MetricActivation* activation = config.add_metric_activation();
+ activation->set_metric_id(12345);
+ EventActivation* eventActivation = activation->add_event_activation();
+ eventActivation->set_atom_matcher_id(startMatcher.id());
+ eventActivation->set_ttl_seconds(5);
+
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}};
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestEventMetricWhatChanged) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers = {whatMatcher.id()};
+ set<int64_t> replacedConditions;
+ unordered_map<int64_t, int> metricToActivationMap;
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestEventMetricConditionChanged) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions = {predicate.id()};
+ unordered_map<int64_t, int> metricToActivationMap;
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestMetricConditionLinkDepsChanged) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ Predicate linkPredicate = CreateScreenIsOffPredicate();
+ *config.add_predicate() = linkPredicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+ // Doesn't make sense as a real metric definition, but suffices as a separate predicate
+ // From the one in the condition.
+ MetricConditionLink* link = metric->add_links();
+ link->set_condition(linkPredicate.id());
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions = {linkPredicate.id()};
+ unordered_map<int64_t, int> metricToActivationMap;
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestEventMetricActivationDepsChange) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(12345);
+ metric->set_what(whatMatcher.id());
+ metric->set_condition(predicate.id());
+
+ MetricActivation* activation = config.add_metric_activation();
+ activation->set_metric_id(12345);
+ EventActivation* eventActivation = activation->add_event_activation();
+ eventActivation->set_atom_matcher_id(startMatcher.id());
+ eventActivation->set_ttl_seconds(5);
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers = {startMatcher.id()}; // The activation matcher is replaced.
+ set<int64_t> replacedConditions;
+ unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}};
+ UpdateStatus status = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineEventMetricUpdateStatus(config, *metric, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, status));
+ EXPECT_EQ(status, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateEventMetrics) {
+ StatsdConfig config;
+
+ // Add atom matchers/predicates. These are mostly needed for initStatsdConfig
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ Predicate predicate1 = CreateScreenIsOnPredicate();
+ int64_t predicate1Id = predicate1.id();
+ *config.add_predicate() = predicate1;
+
+ Predicate predicate2 = CreateScheduledJobPredicate();
+ int64_t predicate2Id = predicate2.id();
+ *config.add_predicate() = predicate2;
+
+ // Add a few event metrics.
+ // Will be preserved.
+ EventMetric event1 = createEventMetric("EVENT1", matcher1Id, predicate2Id);
+ int64_t event1Id = event1.id();
+ *config.add_event_metric() = event1;
+
+ // Will be replaced.
+ EventMetric event2 = createEventMetric("EVENT2", matcher2Id, nullopt);
+ int64_t event2Id = event2.id();
+ *config.add_event_metric() = event2;
+
+ // Will be replaced.
+ EventMetric event3 = createEventMetric("EVENT3", matcher3Id, nullopt);
+ int64_t event3Id = event3.id();
+ *config.add_event_metric() = event3;
+
+ MetricActivation event3Activation;
+ event3Activation.set_metric_id(event3Id);
+ EventActivation* eventActivation = event3Activation.add_event_activation();
+ eventActivation->set_atom_matcher_id(matcher5Id);
+ eventActivation->set_ttl_seconds(5);
+ *config.add_metric_activation() = event3Activation;
+
+ // Will be replaced.
+ EventMetric event4 = createEventMetric("EVENT4", matcher4Id, predicate1Id);
+ int64_t event4Id = event4.id();
+ *config.add_event_metric() = event4;
+
+ // Will be deleted.
+ EventMetric event5 = createEventMetric("EVENT5", matcher5Id, nullopt);
+ int64_t event5Id = event5.id();
+ *config.add_event_metric() = event5;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Used later to ensure the condition wizard is replaced. Get it before doing the update.
+ sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), oldMetricProducers.size() + 1);
+
+ // Add a condition to event2, causing it to be replaced.
+ event2.set_condition(predicate1Id);
+
+ // Mark matcher 5 as replaced. Causes event3 to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher5Id);
+
+ // Mark predicate 1 as replaced. Causes event4 to be replaced.
+ set<int64_t> replacedConditions;
+ replacedConditions.insert(predicate1Id);
+
+ // Fake that predicate 2 is true.
+ ASSERT_EQ(oldMetricProducers[0]->getMetricId(), event1Id);
+ oldMetricProducers[0]->onConditionChanged(true, /*timestamp=*/0);
+ EXPECT_EQ(oldMetricProducers[0]->mCondition, ConditionState::kTrue);
+
+ // New event metric. Should have an initial condition of true since it depends on predicate2.
+ EventMetric event6 = createEventMetric("EVENT6", matcher3Id, predicate2Id);
+ int64_t event6Id = event6.id();
+ MetricActivation event6Activation;
+ event6Activation.set_metric_id(event6Id);
+ eventActivation = event6Activation.add_event_activation();
+ eventActivation->set_atom_matcher_id(matcher5Id);
+ eventActivation->set_ttl_seconds(20);
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher5Index = 0;
+ newAtomMatchingTrackerMap[matcher5Id] = 0;
+ const int matcher4Index = 1;
+ newAtomMatchingTrackerMap[matcher4Id] = 1;
+ const int matcher3Index = 2;
+ newAtomMatchingTrackerMap[matcher3Id] = 2;
+ const int matcher2Index = 3;
+ newAtomMatchingTrackerMap[matcher2Id] = 3;
+ const int matcher1Index = 4;
+ newAtomMatchingTrackerMap[matcher1Id] = 4;
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5);
+ std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+
+ std::unordered_map<int64_t, int> newConditionTrackerMap;
+ const int predicate2Index = 0;
+ newConditionTrackerMap[predicate2Id] = 0;
+ const int predicate1Index = 1;
+ newConditionTrackerMap[predicate1Id] = 1;
+ // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<ConditionTracker>> newConditionTrackers(2);
+ std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+ newConditionTrackers.begin());
+ // Fake that predicate2 is true.
+ vector<ConditionState> conditionCache = {ConditionState::kTrue, ConditionState::kUnknown};
+
+ StatsdConfig newConfig;
+ *newConfig.add_event_metric() = event6;
+ const int event6Index = 0;
+ *newConfig.add_event_metric() = event3;
+ const int event3Index = 1;
+ *newConfig.add_event_metric() = event1;
+ const int event1Index = 2;
+ *newConfig.add_event_metric() = event4;
+ const int event4Index = 3;
+ *newConfig.add_event_metric() = event2;
+ const int event2Index = 4;
+ *newConfig.add_metric_activation() = event3Activation;
+ *newConfig.add_metric_activation() = event6Activation;
+
+ // Output data structures to validate.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ unordered_map<int64_t, int> expectedMetricProducerMap = {
+ {event1Id, event1Index}, {event2Id, event2Index}, {event3Id, event3Index},
+ {event4Id, event4Index}, {event6Id, event6Index},
+ };
+ EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+ // Make sure preserved metrics are the same.
+ ASSERT_EQ(newMetricProducers.size(), 5);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(event1Id)],
+ newMetricProducers[newMetricProducerMap.at(event1Id)]);
+
+ // Make sure replaced conditions are different and included in replacedConditions.
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event2Id)],
+ newMetricProducers[newMetricProducerMap.at(event2Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event3Id)],
+ newMetricProducers[newMetricProducerMap.at(event3Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event4Id)],
+ newMetricProducers[newMetricProducerMap.at(event4Id)]);
+
+ // Verify the conditionToMetricMap.
+ ASSERT_EQ(conditionToMetricMap.size(), 2);
+ const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index];
+ EXPECT_THAT(condition1Metrics, UnorderedElementsAre(event2Index, event4Index));
+ const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index];
+ EXPECT_THAT(condition2Metrics, UnorderedElementsAre(event1Index, event6Index));
+
+ // Verify the trackerToMetricMap.
+ ASSERT_EQ(trackerToMetricMap.size(), 4);
+ const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(event1Index));
+ const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
+ EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(event2Index));
+ const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+ EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(event3Index, event6Index));
+ const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index];
+ EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(event4Index));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 1);
+ EXPECT_THAT(activationAtomTrackerToMetricMap[matcher5Index],
+ UnorderedElementsAre(event3Index, event6Index));
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(metricsWithActivation.size(), 2);
+ EXPECT_THAT(metricsWithActivation, UnorderedElementsAre(event3Index, event6Index));
+
+ // Verify tracker indices/ids/conditions are correct.
+ EXPECT_EQ(newMetricProducers[event1Index]->getMetricId(), event1Id);
+ EXPECT_EQ(newMetricProducers[event1Index]->mConditionTrackerIndex, predicate2Index);
+ EXPECT_EQ(newMetricProducers[event1Index]->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(newMetricProducers[event2Index]->getMetricId(), event2Id);
+ EXPECT_EQ(newMetricProducers[event2Index]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[event2Index]->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(newMetricProducers[event3Index]->getMetricId(), event3Id);
+ EXPECT_EQ(newMetricProducers[event3Index]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[event3Index]->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(newMetricProducers[event4Index]->getMetricId(), event4Id);
+ EXPECT_EQ(newMetricProducers[event4Index]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[event4Index]->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(newMetricProducers[event6Index]->getMetricId(), event6Id);
+ EXPECT_EQ(newMetricProducers[event6Index]->mConditionTrackerIndex, predicate2Index);
+ EXPECT_EQ(newMetricProducers[event6Index]->mCondition, ConditionState::kTrue);
+
+ sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
+ EXPECT_NE(newConditionWizard, oldConditionWizard);
+ EXPECT_EQ(newConditionWizard->getStrongCount(), newMetricProducers.size() + 1);
+ oldMetricProducers.clear();
+ // Only reference to the old wizard should be the one in the test.
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
+ StatsdConfig config;
+ // Add atom matchers
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ // Add an event metric with multiple activations.
+ EventMetric event1 = createEventMetric("EVENT1", matcher1Id, nullopt);
+ int64_t event1Id = event1.id();
+ *config.add_event_metric() = event1;
+
+ int64_t matcher2TtlSec = 2, matcher3TtlSec = 3, matcher4TtlSec = 4;
+ MetricActivation metricActivation;
+ metricActivation.set_metric_id(event1Id);
+ EventActivation* activation = metricActivation.add_event_activation();
+ activation->set_atom_matcher_id(matcher2Id);
+ activation->set_ttl_seconds(matcher2TtlSec);
+ activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+ activation->set_deactivation_atom_matcher_id(matcher1Id);
+ activation = metricActivation.add_event_activation();
+ activation->set_atom_matcher_id(matcher3Id);
+ activation->set_ttl_seconds(matcher3TtlSec);
+ activation->set_activation_type(ACTIVATE_ON_BOOT);
+ activation->set_deactivation_atom_matcher_id(matcher1Id);
+ activation = metricActivation.add_event_activation();
+ activation->set_atom_matcher_id(matcher4Id);
+ activation->set_ttl_seconds(matcher4TtlSec);
+ activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+ activation->set_deactivation_atom_matcher_id(matcher2Id);
+ *config.add_metric_activation() = metricActivation;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Activate some of the event activations.
+ ASSERT_EQ(oldMetricProducers[0]->getMetricId(), event1Id);
+ int64_t matcher2StartNs = 12345;
+ oldMetricProducers[0]->activate(oldAtomMatchingTrackerMap[matcher2Id], matcher2StartNs);
+ int64_t matcher3StartNs = 23456;
+ oldMetricProducers[0]->activate(oldAtomMatchingTrackerMap[matcher3Id], matcher3StartNs);
+ EXPECT_TRUE(oldMetricProducers[0]->isActive());
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher4Index = 0;
+ newAtomMatchingTrackerMap[matcher4Id] = 0;
+ const int matcher3Index = 1;
+ newAtomMatchingTrackerMap[matcher3Id] = 1;
+ const int matcher2Index = 2;
+ newAtomMatchingTrackerMap[matcher2Id] = 2;
+ const int matcher1Index = 3;
+ newAtomMatchingTrackerMap[matcher1Id] = 3;
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(4);
+ std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+ set<int64_t> replacedMatchers;
+
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ set<int64_t> replacedConditions;
+ vector<ConditionState> conditionCache;
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 3);
+ EXPECT_THAT(activationAtomTrackerToMetricMap[matcher2Index], UnorderedElementsAre(0));
+ EXPECT_THAT(activationAtomTrackerToMetricMap[matcher3Index], UnorderedElementsAre(0));
+ EXPECT_THAT(activationAtomTrackerToMetricMap[matcher4Index], UnorderedElementsAre(0));
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 2);
+ EXPECT_THAT(deactivationAtomTrackerToMetricMap[matcher1Index], UnorderedElementsAre(0, 0));
+ EXPECT_THAT(deactivationAtomTrackerToMetricMap[matcher2Index], UnorderedElementsAre(0));
+ ASSERT_EQ(metricsWithActivation.size(), 1);
+ EXPECT_THAT(metricsWithActivation, UnorderedElementsAre(0));
+
+ // Verify mEventActivation and mEventDeactivation map of the producer.
+ sp<MetricProducer> producer = newMetricProducers[0];
+ EXPECT_TRUE(producer->isActive());
+ ASSERT_EQ(producer->mEventActivationMap.size(), 3);
+ shared_ptr<Activation> matcher2Activation = producer->mEventActivationMap[matcher2Index];
+ EXPECT_EQ(matcher2Activation->ttl_ns, matcher2TtlSec * NS_PER_SEC);
+ EXPECT_EQ(matcher2Activation->activationType, ACTIVATE_IMMEDIATELY);
+ EXPECT_EQ(matcher2Activation->state, kActive);
+ EXPECT_EQ(matcher2Activation->start_ns, matcher2StartNs);
+ shared_ptr<Activation> matcher3Activation = producer->mEventActivationMap[matcher3Index];
+ EXPECT_EQ(matcher3Activation->ttl_ns, matcher3TtlSec * NS_PER_SEC);
+ EXPECT_EQ(matcher3Activation->activationType, ACTIVATE_ON_BOOT);
+ EXPECT_EQ(matcher3Activation->state, kActiveOnBoot);
+ shared_ptr<Activation> matcher4Activation = producer->mEventActivationMap[matcher4Index];
+ EXPECT_EQ(matcher4Activation->ttl_ns, matcher4TtlSec * NS_PER_SEC);
+ EXPECT_EQ(matcher4Activation->activationType, ACTIVATE_IMMEDIATELY);
+ EXPECT_EQ(matcher4Activation->state, kNotActive);
+
+ ASSERT_EQ(producer->mEventDeactivationMap.size(), 2);
+ EXPECT_THAT(producer->mEventDeactivationMap[matcher1Index],
+ UnorderedElementsAre(matcher2Activation, matcher3Activation));
+ EXPECT_THAT(producer->mEventDeactivationMap[matcher2Index],
+ UnorderedElementsAre(matcher4Activation));
+}
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 1f8cf8ac6d1d..a2d0b892aa0a 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -46,20 +46,39 @@ public abstract class ActivityManagerInternal {
// Access modes for handleIncomingUser.
+ /**
+ * Allows access to a caller with {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
+ */
public static final int ALLOW_NON_FULL = 0;
/**
* Allows access to a caller with {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
- * if in the same profile group.
+ * or {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} if in the same profile
+ * group.
* Otherwise, {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} is required.
*/
- public static final int ALLOW_NON_FULL_IN_PROFILE = 1;
+ public static final int ALLOW_NON_FULL_IN_PROFILE_OR_FULL = 1;
+ /**
+ * Allows access to a caller with {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+ * only.
+ */
public static final int ALLOW_FULL_ONLY = 2;
/**
* Allows access to a caller with {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
- * or {@link android.Manifest.permission#INTERACT_ACROSS_USERS} if in the same profile group.
+ * or {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} if in the same profile group.
* Otherwise, {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} is required.
*/
- public static final int ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE = 3;
+ public static final int ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL = 3;
+ /**
+ * Requires {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS}, or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} if in same profile group,
+ * otherwise {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}. (so this is an extension
+ * to {@link #ALLOW_NON_FULL})
+ */
+ public static final int ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL = 4;
/**
* Verify that calling app has access to the given provider.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0fd0e02a224a..312d122d0ba4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -614,7 +614,7 @@ public final class ActivityThread extends ClientTransactionHandler {
throw new IllegalStateException(
"Received config update for non-existing activity");
}
- activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig,
+ activity.mMainThread.handleActivityConfigurationChanged(this, overrideConfig,
newDisplayId);
};
}
@@ -3475,13 +3475,9 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
- final ActivityClientRecord r = mActivities.get(token);
+ public void handleStartActivity(ActivityClientRecord r,
+ PendingTransactionActions pendingActions) {
final Activity activity = r.activity;
- if (r.activity == null) {
- // TODO(lifecycler): What do we do in this case?
- return;
- }
if (!r.stopped) {
throw new IllegalStateException("Can't start activity that is not stopped.");
}
@@ -3687,12 +3683,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleNewIntent(IBinder token, List<ReferrerIntent> intents) {
- final ActivityClientRecord r = mActivities.get(token);
- if (r == null) {
- return;
- }
-
+ public void handleNewIntent(ActivityClientRecord r, List<ReferrerIntent> intents) {
checkAndBlockForNetworkAccess();
deliverNewIntents(r, intents);
}
@@ -3881,13 +3872,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handlePictureInPictureRequested(IBinder token) {
- final ActivityClientRecord r = mActivities.get(token);
- if (r == null) {
- Log.w(TAG, "Activity to request PIP to no longer exists");
- return;
- }
-
+ public void handlePictureInPictureRequested(ActivityClientRecord r) {
final boolean receivedByApp = r.activity.onPictureInPictureRequested();
if (!receivedByApp) {
// Previous recommendation was for apps to enter picture-in-picture in
@@ -4417,22 +4402,21 @@ public final class ActivityThread extends ClientTransactionHandler {
/**
* Resume the activity.
- * @param token Target activity token.
+ * @param r Target activity record.
* @param finalStateRequest Flag indicating if this is part of final state resolution for a
* transaction.
* @param reason Reason for performing the action.
*
- * @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise.
+ * @return {@code true} that was resumed, {@code false} otherwise.
*/
@VisibleForTesting
- public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
+ public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
String reason) {
- final ActivityClientRecord r = mActivities.get(token);
if (localLOGV) {
Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
}
- if (r == null || r.activity.mFinished) {
- return null;
+ if (r.activity.mFinished) {
+ return false;
}
if (r.getLifecycleState() == ON_RESUME) {
if (!finalStateRequest) {
@@ -4446,7 +4430,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// handle two resume requests for the final state. For cases other than this
// one, we don't expect it to happen.
}
- return null;
+ return false;
}
if (finalStateRequest) {
r.hideForNow = false;
@@ -4477,7 +4461,7 @@ public final class ActivityThread extends ClientTransactionHandler {
+ r.intent.getComponent().toShortString() + ": " + e.toString(), e);
}
}
- return r;
+ return true;
}
static final void cleanUpPendingRemoveWindows(ActivityClientRecord r, boolean force) {
@@ -4498,20 +4482,19 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
- String reason) {
+ public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
+ boolean isForward, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
- final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
- if (r == null) {
- // We didn't actually resume the activity, so skipping any follow-up actions.
+ // skip below steps for double-resume and r.mFinish = true case.
+ if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
- if (mActivitiesToBeDestroyed.containsKey(token)) {
+ if (mActivitiesToBeDestroyed.containsKey(r.token)) {
// Although the activity is resumed, it is going to be destroyed. So the following
// UI operations are unnecessary and also prevents exception because its token may
// be gone that window manager cannot recognize it. All necessary cleanup actions
@@ -4629,13 +4612,8 @@ public final class ActivityThread extends ClientTransactionHandler {
@Override
- public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) {
- ActivityClientRecord r = mActivities.get(token);
- if (r == null || r.activity == null) {
- Slog.w(TAG, "Not found target activity to report position change for token: " + token);
- return;
- }
-
+ public void handleTopResumedActivityChanged(ActivityClientRecord r, boolean onTop,
+ String reason) {
if (DEBUG_ORDER) {
Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r);
}
@@ -4668,23 +4646,20 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
+ public void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
- ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
- if (userLeaving) {
- performUserLeavingActivity(r);
- }
+ if (userLeaving) {
+ performUserLeavingActivity(r);
+ }
- r.activity.mConfigChangeFlags |= configChanges;
- performPauseActivity(r, finished, reason, pendingActions);
+ r.activity.mConfigChangeFlags |= configChanges;
+ performPauseActivity(r, finished, reason, pendingActions);
- // Make sure any pending writes are now committed.
- if (r.isPreHoneycomb()) {
- QueuedWork.waitToFinish();
- }
- mSomeActivitiesChanged = true;
+ // Make sure any pending writes are now committed.
+ if (r.isPreHoneycomb()) {
+ QueuedWork.waitToFinish();
}
+ mSomeActivitiesChanged = true;
}
final void performUserLeavingActivity(ActivityClientRecord r) {
@@ -4781,8 +4756,11 @@ public final class ActivityThread extends ClientTransactionHandler {
r.setState(ON_PAUSE);
}
+ // TODO(b/127877792): Make LocalActivityManager call performStopActivityInner. We cannot remove
+ // this since it's a high usage hidden API.
/** Called from {@link LocalActivityManager}. */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 127877792,
+ publicAlternatives = "{@code N/A}")
final void performStopActivity(IBinder token, boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,
@@ -4823,44 +4801,42 @@ public final class ActivityThread extends ClientTransactionHandler {
private void performStopActivityInner(ActivityClientRecord r, StopInfo info,
boolean saveState, boolean finalStateRequest, String reason) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
- if (r != null) {
- if (r.stopped) {
- if (r.activity.mFinished) {
- // If we are finishing, we won't call onResume() in certain
- // cases. So here we likewise don't want to call onStop()
- // if the activity isn't resumed.
- return;
- }
- if (!finalStateRequest) {
- final RuntimeException e = new RuntimeException(
- "Performing stop of activity that is already stopped: "
- + r.intent.getComponent().toShortString());
- Slog.e(TAG, e.getMessage(), e);
- Slog.e(TAG, r.getStateString());
- }
+ if (r.stopped) {
+ if (r.activity.mFinished) {
+ // If we are finishing, we won't call onResume() in certain
+ // cases. So here we likewise don't want to call onStop()
+ // if the activity isn't resumed.
+ return;
}
+ if (!finalStateRequest) {
+ final RuntimeException e = new RuntimeException(
+ "Performing stop of activity that is already stopped: "
+ + r.intent.getComponent().toShortString());
+ Slog.e(TAG, e.getMessage(), e);
+ Slog.e(TAG, r.getStateString());
+ }
+ }
- // One must first be paused before stopped...
- performPauseActivityIfNeeded(r, reason);
+ // One must first be paused before stopped...
+ performPauseActivityIfNeeded(r, reason);
- if (info != null) {
- try {
- // First create a thumbnail for the activity...
- // For now, don't create the thumbnail here; we are
- // doing that by doing a screen snapshot.
- info.setDescription(r.activity.onCreateDescription());
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to save state of activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
+ if (info != null) {
+ try {
+ // First create a thumbnail for the activity...
+ // For now, don't create the thumbnail here; we are
+ // doing that by doing a screen snapshot.
+ info.setDescription(r.activity.onCreateDescription());
+ } catch (Exception e) {
+ if (!mInstrumentation.onException(r.activity, e)) {
+ throw new RuntimeException(
+ "Unable to save state of activity "
+ + r.intent.getComponent().toShortString()
+ + ": " + e.toString(), e);
}
}
-
- callActivityOnStop(r, saveState, reason);
}
+
+ callActivityOnStop(r, saveState, reason);
}
/**
@@ -4927,9 +4903,8 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStopActivity(IBinder token, int configChanges,
+ public void handleStopActivity(ActivityClientRecord r, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
- final ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
final StopInfo stopInfo = new StopInfo();
@@ -4965,8 +4940,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void performRestartActivity(IBinder token, boolean start) {
- ActivityClientRecord r = mActivities.get(token);
+ public void performRestartActivity(ActivityClientRecord r, boolean start) {
if (r.stopped) {
r.activity.performRestart(start, "performRestartActivity");
if (start) {
@@ -5053,110 +5027,98 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleSendResult(IBinder token, List<ResultInfo> results, String reason) {
- ActivityClientRecord r = mActivities.get(token);
+ public void handleSendResult(ActivityClientRecord r, List<ResultInfo> results, String reason) {
if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
- if (r != null) {
- final boolean resumed = !r.paused;
- if (!r.activity.mFinished && r.activity.mDecor != null
- && r.hideForNow && resumed) {
- // We had hidden the activity because it started another
- // one... we have gotten a result back and we are not
- // paused, so make sure our window is visible.
- updateVisibility(r, true);
- }
- if (resumed) {
- try {
- // Now we are idle.
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnPause(r.activity);
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString()
- + " did not call through to super.onPause()");
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to pause activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
+ final boolean resumed = !r.paused;
+ if (!r.activity.mFinished && r.activity.mDecor != null
+ && r.hideForNow && resumed) {
+ // We had hidden the activity because it started another
+ // one... we have gotten a result back and we are not
+ // paused, so make sure our window is visible.
+ updateVisibility(r, true);
+ }
+ if (resumed) {
+ try {
+ // Now we are idle.
+ r.activity.mCalled = false;
+ mInstrumentation.callActivityOnPause(r.activity);
+ if (!r.activity.mCalled) {
+ throw new SuperNotCalledException(
+ "Activity " + r.intent.getComponent().toShortString()
+ + " did not call through to super.onPause()");
+ }
+ } catch (SuperNotCalledException e) {
+ throw e;
+ } catch (Exception e) {
+ if (!mInstrumentation.onException(r.activity, e)) {
+ throw new RuntimeException(
+ "Unable to pause activity "
+ + r.intent.getComponent().toShortString()
+ + ": " + e.toString(), e);
}
- }
- checkAndBlockForNetworkAccess();
- deliverResults(r, results, reason);
- if (resumed) {
- r.activity.performResume(false, reason);
}
}
+ checkAndBlockForNetworkAccess();
+ deliverResults(r, results, reason);
+ if (resumed) {
+ r.activity.performResume(false, reason);
+ }
}
/** Core implementation of activity destroy call. */
- ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
+ void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
- ActivityClientRecord r = mActivities.get(token);
Class<? extends Activity> activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
- if (r != null) {
- activityClass = r.activity.getClass();
- r.activity.mConfigChangeFlags |= configChanges;
- if (finishing) {
- r.activity.mFinished = true;
- }
+ activityClass = r.activity.getClass();
+ r.activity.mConfigChangeFlags |= configChanges;
+ if (finishing) {
+ r.activity.mFinished = true;
+ }
- performPauseActivityIfNeeded(r, "destroy");
+ performPauseActivityIfNeeded(r, "destroy");
- if (!r.stopped) {
- callActivityOnStop(r, false /* saveState */, "destroy");
- }
- if (getNonConfigInstance) {
- try {
- r.lastNonConfigurationInstances
- = r.activity.retainNonConfigurationInstances();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to retain activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
+ if (!r.stopped) {
+ callActivityOnStop(r, false /* saveState */, "destroy");
+ }
+ if (getNonConfigInstance) {
try {
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnDestroy(r.activity);
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + safeToComponentShortString(r.intent) +
- " did not call through to super.onDestroy()");
- }
- if (r.window != null) {
- r.window.closeAllPanels();
- }
- } catch (SuperNotCalledException e) {
- throw e;
+ r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to destroy activity " + safeToComponentShortString(r.intent)
- + ": " + e.toString(), e);
+ throw new RuntimeException("Unable to retain activity "
+ + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
}
}
- r.setState(ON_DESTROY);
- mLastReportedWindowingMode.remove(r.activity.getActivityToken());
}
+ try {
+ r.activity.mCalled = false;
+ mInstrumentation.callActivityOnDestroy(r.activity);
+ if (!r.activity.mCalled) {
+ throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
+ + " did not call through to super.onDestroy()");
+ }
+ if (r.window != null) {
+ r.window.closeAllPanels();
+ }
+ } catch (SuperNotCalledException e) {
+ throw e;
+ } catch (Exception e) {
+ if (!mInstrumentation.onException(r.activity, e)) {
+ throw new RuntimeException("Unable to destroy activity "
+ + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
+ }
+ }
+ r.setState(ON_DESTROY);
+ mLastReportedWindowingMode.remove(r.activity.getActivityToken());
schedulePurgeIdler();
// updatePendingActivityConfiguration() reads from mActivities to update
// ActivityClientRecord which runs in a different thread. Protect modifications to
// mActivities to avoid race.
synchronized (mResourcesManager) {
- mActivities.remove(token);
+ mActivities.remove(r.token);
}
StrictMode.decrementExpectedActivityCount(activityClass);
- return r;
}
private static String safeToComponentShortString(Intent intent) {
@@ -5170,70 +5132,65 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
+ public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
- ActivityClientRecord r = performDestroyActivity(token, finishing,
- configChanges, getNonConfigInstance, reason);
- if (r != null) {
- cleanUpPendingRemoveWindows(r, finishing);
- WindowManager wm = r.activity.getWindowManager();
- View v = r.activity.mDecor;
- if (v != null) {
- if (r.activity.mVisibleFromServer) {
- mNumVisibleActivities--;
- }
- IBinder wtoken = v.getWindowToken();
- if (r.activity.mWindowAdded) {
- if (r.mPreserveWindow) {
- // Hold off on removing this until the new activity's
- // window is being added.
- r.mPendingRemoveWindow = r.window;
- r.mPendingRemoveWindowManager = wm;
- // We can only keep the part of the view hierarchy that we control,
- // everything else must be removed, because it might not be able to
- // behave properly when activity is relaunching.
- r.window.clearContentView();
- } else {
- wm.removeViewImmediate(v);
- }
- }
- if (wtoken != null && r.mPendingRemoveWindow == null) {
- WindowManagerGlobal.getInstance().closeAll(wtoken,
- r.activity.getClass().getName(), "Activity");
- } else if (r.mPendingRemoveWindow != null) {
- // We're preserving only one window, others should be closed so app views
- // will be detached before the final tear down. It should be done now because
- // some components (e.g. WebView) rely on detach callbacks to perform receiver
- // unregister and other cleanup.
- WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
- r.activity.getClass().getName(), "Activity");
+ performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
+ cleanUpPendingRemoveWindows(r, finishing);
+ WindowManager wm = r.activity.getWindowManager();
+ View v = r.activity.mDecor;
+ if (v != null) {
+ if (r.activity.mVisibleFromServer) {
+ mNumVisibleActivities--;
+ }
+ IBinder wtoken = v.getWindowToken();
+ if (r.activity.mWindowAdded) {
+ if (r.mPreserveWindow) {
+ // Hold off on removing this until the new activity's window is being added.
+ r.mPendingRemoveWindow = r.window;
+ r.mPendingRemoveWindowManager = wm;
+ // We can only keep the part of the view hierarchy that we control,
+ // everything else must be removed, because it might not be able to
+ // behave properly when activity is relaunching.
+ r.window.clearContentView();
+ } else {
+ wm.removeViewImmediate(v);
}
- r.activity.mDecor = null;
- }
- if (r.mPendingRemoveWindow == null) {
- // If we are delaying the removal of the activity window, then
- // we can't clean up all windows here. Note that we can't do
- // so later either, which means any windows that aren't closed
- // by the app will leak. Well we try to warning them a lot
- // about leaking windows, because that is a bug, so if they are
- // using this recreate facility then they get to live with leaks.
- WindowManagerGlobal.getInstance().closeAll(token,
- r.activity.getClass().getName(), "Activity");
}
-
- // Mocked out contexts won't be participating in the normal
- // process lifecycle, but if we're running with a proper
- // ApplicationContext we need to have it tear down things
- // cleanly.
- Context c = r.activity.getBaseContext();
- if (c instanceof ContextImpl) {
- ((ContextImpl) c).scheduleFinalCleanup(
+ if (wtoken != null && r.mPendingRemoveWindow == null) {
+ WindowManagerGlobal.getInstance().closeAll(wtoken,
+ r.activity.getClass().getName(), "Activity");
+ } else if (r.mPendingRemoveWindow != null) {
+ // We're preserving only one window, others should be closed so app views
+ // will be detached before the final tear down. It should be done now because
+ // some components (e.g. WebView) rely on detach callbacks to perform receiver
+ // unregister and other cleanup.
+ WindowManagerGlobal.getInstance().closeAllExceptView(r.token, v,
r.activity.getClass().getName(), "Activity");
}
+ r.activity.mDecor = null;
+ }
+ if (r.mPendingRemoveWindow == null) {
+ // If we are delaying the removal of the activity window, then
+ // we can't clean up all windows here. Note that we can't do
+ // so later either, which means any windows that aren't closed
+ // by the app will leak. Well we try to warning them a lot
+ // about leaking windows, because that is a bug, so if they are
+ // using this recreate facility then they get to live with leaks.
+ WindowManagerGlobal.getInstance().closeAll(r.token,
+ r.activity.getClass().getName(), "Activity");
+ }
+
+ // Mocked out contexts won't be participating in the normal
+ // process lifecycle, but if we're running with a proper
+ // ApplicationContext we need to have it tear down things
+ // cleanly.
+ Context c = r.activity.getBaseContext();
+ if (c instanceof ContextImpl) {
+ ((ContextImpl) c).scheduleFinalCleanup(r.activity.getClass().getName(), "Activity");
}
if (finishing) {
try {
- ActivityTaskManager.getService().activityDestroyed(token);
+ ActivityTaskManager.getService().activityDestroyed(r.token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -5455,7 +5412,7 @@ public final class ActivityThread extends ClientTransactionHandler {
callActivityOnStop(r, true /* saveState */, reason);
}
- handleDestroyActivity(r.token, false, configChanges, true, reason);
+ handleDestroyActivity(r, false, configChanges, true, reason);
r.activity = null;
r.window = null;
@@ -5483,12 +5440,10 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) {
+ public void reportRelaunch(ActivityClientRecord r, PendingTransactionActions pendingActions) {
try {
- ActivityTaskManager.getService().activityRelaunched(token);
- final ActivityClientRecord r = mActivities.get(token);
- if (pendingActions.shouldReportRelaunchToWindowManager() && r != null
- && r.window != null) {
+ ActivityTaskManager.getService().activityRelaunched(r.token);
+ if (pendingActions.shouldReportRelaunchToWindowManager() && r.window != null) {
r.window.reportActivityRelaunched();
}
} catch (RemoteException e) {
@@ -5647,13 +5602,7 @@ public final class ActivityThread extends ClientTransactionHandler {
*/
private Configuration performActivityConfigurationChanged(Activity activity,
Configuration newConfig, Configuration amOverrideConfig, int displayId) {
- if (activity == null) {
- throw new IllegalArgumentException("No activity provided.");
- }
final IBinder activityToken = activity.getActivityToken();
- if (activityToken == null) {
- throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
- }
// WindowConfiguration differences aren't considered as public, check it separately.
// multi-window / pip mode changes, if any, should be sent before the configuration
@@ -5952,20 +5901,8 @@ public final class ActivityThread extends ClientTransactionHandler {
* processing any configurations older than {@code overrideConfig}.
*/
@Override
- public void updatePendingActivityConfiguration(IBinder activityToken,
+ public void updatePendingActivityConfiguration(ActivityClientRecord r,
Configuration overrideConfig) {
- final ActivityClientRecord r;
- synchronized (mResourcesManager) {
- r = mActivities.get(activityToken);
- }
-
- if (r == null) {
- if (DEBUG_CONFIGURATION) {
- Slog.w(TAG, "Not found target activity to update its pending config.");
- }
- return;
- }
-
synchronized (r) {
if (r.mPendingOverrideConfig != null
&& !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
@@ -5985,21 +5922,14 @@ public final class ActivityThread extends ClientTransactionHandler {
* if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with
* a newer config than {@code overrideConfig}.
*
- * @param activityToken Target activity token.
+ * @param r Target activity record.
* @param overrideConfig Activity override config.
* @param displayId Id of the display where activity was moved to, -1 if there was no move and
* value didn't change.
*/
@Override
- public void handleActivityConfigurationChanged(IBinder activityToken,
+ public void handleActivityConfigurationChanged(ActivityClientRecord r,
@NonNull Configuration overrideConfig, int displayId) {
- ActivityClientRecord r = mActivities.get(activityToken);
- // Check input params.
- if (r == null || r.activity == null) {
- if (DEBUG_CONFIGURATION) Slog.w(TAG, "Not found target activity to report to: " + r);
- return;
- }
-
synchronized (r) {
if (overrideConfig.isOtherSeqNewer(r.mPendingOverrideConfig)) {
if (DEBUG_CONFIGURATION) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 167b5a8029c0..04f72f6dc71d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -6741,10 +6741,14 @@ public class AppOpsManager {
*/
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(int code, int uid, @Mode int mode) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
mService.setUidMode(code, uid, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -6762,11 +6766,7 @@ public class AppOpsManager {
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
- try {
- mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
}
/** @hide */
@@ -6795,10 +6795,14 @@ public class AppOpsManager {
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(int code, int uid, String packageName, @Mode int mode) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
mService.setMode(code, uid, packageName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -6818,11 +6822,7 @@ public class AppOpsManager {
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(@NonNull String op, int uid, @Nullable String packageName,
@Mode int mode) {
- try {
- mService.setMode(strOpToOp(op), uid, packageName, mode);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ setMode(strOpToOp(op), uid, packageName, mode);
}
/**
@@ -7298,10 +7298,14 @@ public class AppOpsManager {
* @hide
*/
public int unsafeCheckOpRawNoThrow(int op, int uid, @NonNull String packageName) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
return mService.checkOperationRaw(op, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -7473,8 +7477,20 @@ public class AppOpsManager {
}
}
- int mode = mService.noteOperation(op, uid, packageName, attributionTag,
- collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
+ int mode;
+ // Making the binder call "noteOperation" usually sets Binder.callingUid to the calling
+ // processes UID. Hence clearing the calling UID is superfluous.
+ // If the call is inside the system server though "noteOperation" is not a binder all,
+ // it is only a method call. Hence Binder.callingUid might still be set to the app that
+ // called the system server. This can lead to problems as not every app can see the
+ // same appops the system server can see.
+ long token = Binder.clearCallingIdentity();
+ try {
+ mode = mService.noteOperation(op, uid, packageName, attributionTag,
+ collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -7637,10 +7653,17 @@ public class AppOpsManager {
}
}
- int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
- proxiedAttributionTag, myUid, mContext.getOpPackageName(),
- mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message,
- shouldCollectMessage);
+ int mode;
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
+ try {
+ mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
+ proxiedAttributionTag, myUid, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message,
+ shouldCollectMessage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -7690,6 +7713,8 @@ public class AppOpsManager {
*/
@UnsupportedAppUsage
public int checkOp(int op, int uid, String packageName) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
int mode = mService.checkOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
@@ -7698,6 +7723,8 @@ public class AppOpsManager {
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -7708,11 +7735,15 @@ public class AppOpsManager {
*/
@UnsupportedAppUsage
public int checkOpNoThrow(int op, int uid, String packageName) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
int mode = mService.checkOperation(op, uid, packageName);
return mode == AppOpsManager.MODE_FOREGROUND ? AppOpsManager.MODE_ALLOWED : mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -7964,9 +7995,16 @@ public class AppOpsManager {
}
}
- int mode = mService.startOperation(getClientId(), op, uid, packageName,
- attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message,
- shouldCollectMessage);
+ int mode;
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
+ try {
+ mode = mService.startOperation(getClientId(), op, uid, packageName,
+ attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC,
+ message, shouldCollectMessage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
@@ -8029,10 +8067,14 @@ public class AppOpsManager {
*/
public void finishOp(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
mService.finishOperation(getClientId(), op, uid, packageName, attributionTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -8624,10 +8666,14 @@ public class AppOpsManager {
// TODO: Uncomment below annotation once b/73559440 is fixed
// @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
public boolean isOperationActive(int code, int uid, String packageName) {
+ // Clear calling UID to handle calls from inside the system server. See #noteOpNoThrow
+ long token = Binder.clearCallingIdentity();
try {
return mService.isOperationActive(code, uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 2df756e80fde..ac50676ff46b 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -15,6 +15,8 @@
*/
package android.app;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.PendingTransactionActions;
@@ -89,37 +91,38 @@ public abstract class ClientTransactionHandler {
public abstract Map<IBinder, ClientTransactionItem> getActivitiesToBeDestroyed();
/** Destroy the activity. */
- public abstract void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
- boolean getNonConfigInstance, String reason);
+ public abstract void handleDestroyActivity(@NonNull ActivityClientRecord r, boolean finishing,
+ int configChanges, boolean getNonConfigInstance, String reason);
/** Pause the activity. */
- public abstract void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
- int configChanges, PendingTransactionActions pendingActions, String reason);
+ public abstract void handlePauseActivity(@NonNull ActivityClientRecord r, boolean finished,
+ boolean userLeaving, int configChanges, PendingTransactionActions pendingActions,
+ String reason);
/**
* Resume the activity.
- * @param token Target activity token.
+ * @param r Target activity record.
* @param finalStateRequest Flag indicating if this call is handling final lifecycle state
* request for a transaction.
* @param isForward Flag indicating if next transition is forward.
* @param reason Reason for performing this operation.
*/
- public abstract void handleResumeActivity(IBinder token, boolean finalStateRequest,
- boolean isForward, String reason);
+ public abstract void handleResumeActivity(@NonNull ActivityClientRecord r,
+ boolean finalStateRequest, boolean isForward, String reason);
/**
* Notify the activity about top resumed state change.
- * @param token Target activity token.
+ * @param r Target activity record.
* @param isTopResumedActivity Current state of the activity, {@code true} if it's the
* topmost resumed activity in the system, {@code false} otherwise.
* @param reason Reason for performing this operation.
*/
- public abstract void handleTopResumedActivityChanged(IBinder token,
+ public abstract void handleTopResumedActivityChanged(@NonNull ActivityClientRecord r,
boolean isTopResumedActivity, String reason);
/**
* Stop the activity.
- * @param token Target activity token.
+ * @param r Target activity record.
* @param configChanges Activity configuration changes.
* @param pendingActions Pending actions to be used on this or later stages of activity
* transaction.
@@ -127,38 +130,40 @@ public abstract class ClientTransactionHandler {
* request for a transaction.
* @param reason Reason for performing this operation.
*/
- public abstract void handleStopActivity(IBinder token, int configChanges,
+ public abstract void handleStopActivity(@NonNull ActivityClientRecord r, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason);
/** Report that activity was stopped to server. */
public abstract void reportStop(PendingTransactionActions pendingActions);
/** Restart the activity after it was stopped. */
- public abstract void performRestartActivity(IBinder token, boolean start);
+ public abstract void performRestartActivity(@NonNull ActivityClientRecord r, boolean start);
/** Set pending activity configuration in case it will be updated by other transaction item. */
- public abstract void updatePendingActivityConfiguration(IBinder activityToken,
+ public abstract void updatePendingActivityConfiguration(@NonNull ActivityClientRecord r,
Configuration overrideConfig);
/** Deliver activity (override) configuration change. */
- public abstract void handleActivityConfigurationChanged(IBinder activityToken,
+ public abstract void handleActivityConfigurationChanged(@NonNull ActivityClientRecord r,
Configuration overrideConfig, int displayId);
/** Deliver result from another activity. */
- public abstract void handleSendResult(IBinder token, List<ResultInfo> results, String reason);
+ public abstract void handleSendResult(
+ @NonNull ActivityClientRecord r, List<ResultInfo> results, String reason);
/** Deliver new intent. */
- public abstract void handleNewIntent(IBinder token, List<ReferrerIntent> intents);
+ public abstract void handleNewIntent(
+ @NonNull ActivityClientRecord r, List<ReferrerIntent> intents);
/** Request that an activity enter picture-in-picture. */
- public abstract void handlePictureInPictureRequested(IBinder token);
+ public abstract void handlePictureInPictureRequested(@NonNull ActivityClientRecord r);
/** Perform activity launch. */
- public abstract Activity handleLaunchActivity(ActivityThread.ActivityClientRecord r,
+ public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent);
/** Perform activity start. */
- public abstract void handleStartActivity(IBinder token,
+ public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
PendingTransactionActions pendingActions);
/** Get package info. */
@@ -176,7 +181,7 @@ public abstract class ClientTransactionHandler {
* Get {@link android.app.ActivityThread.ActivityClientRecord} instance that corresponds to the
* provided token.
*/
- public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token);
+ public abstract ActivityClientRecord getActivityClient(IBinder token);
/**
* Prepare activity relaunch to update internal bookkeeping. This is used to track multiple
@@ -191,7 +196,7 @@ public abstract class ClientTransactionHandler {
* @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during
* relaunch, or {@code null} if relaunch cancelled.
*/
- public abstract ActivityThread.ActivityClientRecord prepareRelaunchActivity(IBinder token,
+ public abstract ActivityClientRecord prepareRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
int configChanges, MergedConfiguration config, boolean preserveWindow);
@@ -200,14 +205,15 @@ public abstract class ClientTransactionHandler {
* @param r Activity client record prepared for relaunch.
* @param pendingActions Pending actions to be used on later stages of activity transaction.
* */
- public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord r,
+ public abstract void handleRelaunchActivity(@NonNull ActivityClientRecord r,
PendingTransactionActions pendingActions);
/**
* Report that relaunch request was handled.
- * @param token Target activity token.
+ * @param r Target activity record.
* @param pendingActions Pending actions initialized on earlier stages of activity transaction.
* Used to check if we should report relaunch to WM.
* */
- public abstract void reportRelaunch(IBinder token, PendingTransactionActions pendingActions);
+ public abstract void reportRelaunch(@NonNull ActivityClientRecord r,
+ PendingTransactionActions pendingActions);
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index fef8d1005e29..cf5a7b629e38 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2413,7 +2413,6 @@ class ContextImpl extends Context {
context.setResources(createResources(mToken, mPackageInfo, mSplitName, overrideDisplayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
- context.mIsUiContext = isSelfOrOuterUiContext();
return context;
}
@@ -2442,6 +2441,11 @@ class ContextImpl extends Context {
// the display that would otherwise be inherited from mToken (or the global configuration if
// mToken is null).
context.mForceDisplayOverrideInResources = 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;
}
@@ -2806,6 +2810,7 @@ class ContextImpl extends Context {
mIsAssociatedWithDisplay = container.mIsAssociatedWithDisplay;
mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext;
mForceDisplayOverrideInResources = container.mForceDisplayOverrideInResources;
+ 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 45b25a3bf317..c1e6f5282b2a 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -513,13 +513,6 @@ interface IActivityManager {
// descriptor.
@UnsupportedAppUsage
boolean stopBinderTrackingAndDump(in ParcelFileDescriptor fd);
- /**
- * Try to place task to provided position. The final position might be different depending on
- * current user and stacks state. The task will be moved to target stack if it's currently in
- * different stack.
- */
- @UnsupportedAppUsage
- void positionTaskInStack(int taskId, int stackId, int position);
@UnsupportedAppUsage
void suppressResizeConfigChanges(boolean suppress);
@UnsupportedAppUsage
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index f3c7fe9412c9..e21ef8ee23ad 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -295,12 +295,6 @@ interface IActivityTaskManager {
ComponentName getActivityClassForToken(in IBinder token);
String getPackageForToken(in IBinder token);
- /**
- * Try to place task to provided position. The final position might be different depending on
- * current user and stacks state. The task will be moved to target stack if it's currently in
- * different stack.
- */
- void positionTaskInStack(int taskId, int stackId, int position);
void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 7cdf85e0a6b8..2e7c9f11ac66 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -49,6 +49,7 @@ public class LocalActivityManager {
private static final String TAG = "LocalActivityManager";
private static final boolean localLOGV = false;
+ // TODO(b/127877792): try to remove this and use {@code ActivityClientRecord} instead.
// Internal token for an Activity being managed by LocalActivityManager.
private static class LocalActivityRecord extends Binder {
LocalActivityRecord(String _id, Intent _intent) {
@@ -136,7 +137,7 @@ public class LocalActivityManager {
// startActivity() has not yet been called, so nothing to do.
return;
}
-
+
if (r.curState == INITIALIZING) {
// Get the lastNonConfigurationInstance for the activity
HashMap<String, Object> lastNonConfigurationInstances =
@@ -177,12 +178,13 @@ public class LocalActivityManager {
pendingActions = null;
}
- mActivityThread.handleStartActivity(r, pendingActions);
+ mActivityThread.handleStartActivity(clientRecord, pendingActions);
r.curState = STARTED;
if (desiredState == RESUMED) {
if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true, "moveToState-INITIALIZING");
+ mActivityThread.performResumeActivity(clientRecord, true,
+ "moveToState-INITIALIZING");
r.curState = RESUMED;
}
@@ -194,18 +196,25 @@ public class LocalActivityManager {
// group's state catches up.
return;
}
-
+
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ if (clientRecord == null) {
+ Log.w(TAG, "Can't get activity record for " + r.id);
+ return;
+ }
+
switch (r.curState) {
case CREATED:
if (desiredState == STARTED) {
if (localLOGV) Log.v(TAG, r.id + ": restarting");
- mActivityThread.performRestartActivity(r, true /* start */);
+ mActivityThread.performRestartActivity(clientRecord, true /* start */);
r.curState = STARTED;
}
if (desiredState == RESUMED) {
if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming");
- mActivityThread.performRestartActivity(r, true /* start */);
- mActivityThread.performResumeActivity(r, true, "moveToState-CREATED");
+ mActivityThread.performRestartActivity(clientRecord, true /* start */);
+ mActivityThread.performResumeActivity(clientRecord, true,
+ "moveToState-CREATED");
r.curState = RESUMED;
}
return;
@@ -214,7 +223,8 @@ public class LocalActivityManager {
if (desiredState == RESUMED) {
// Need to resume it...
if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true, "moveToState-STARTED");
+ mActivityThread.performResumeActivity(clientRecord, true,
+ "moveToState-STARTED");
r.instanceState = null;
r.curState = RESUMED;
}
@@ -352,7 +362,8 @@ public class LocalActivityManager {
ArrayList<ReferrerIntent> intents = new ArrayList<>(1);
intents.add(new ReferrerIntent(intent, mParent.getPackageName()));
if (localLOGV) Log.v(TAG, r.id + ": new intent");
- mActivityThread.handleNewIntent(r, intents);
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ mActivityThread.handleNewIntent(clientRecord, intents);
r.intent = intent;
moveToState(r, mCurState);
if (mSingleMode) {
@@ -399,8 +410,11 @@ public class LocalActivityManager {
performPause(r, finish);
}
if (localLOGV) Log.v(TAG, r.id + ": destroying");
- mActivityThread.performDestroyActivity(r, finish, 0 /* configChanges */,
- false /* getNonConfigInstance */, "LocalActivityManager::performDestroy");
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ if (clientRecord != null) {
+ mActivityThread.performDestroyActivity(clientRecord, finish, 0 /* configChanges */,
+ false /* getNonConfigInstance */, "LocalActivityManager::performDestroy");
+ }
r.activity = null;
r.window = null;
if (finish) {
@@ -664,7 +678,12 @@ public class LocalActivityManager {
for (int i=0; i<N; i++) {
LocalActivityRecord r = mActivityArray.get(i);
if (localLOGV) Log.v(TAG, r.id + ": destroying");
- mActivityThread.performDestroyActivity(r, finishing, 0 /* configChanges */,
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ if (clientRecord == null) {
+ if (localLOGV) Log.v(TAG, r.id + ": no corresponding record");
+ continue;
+ }
+ mActivityThread.performDestroyActivity(clientRecord, finishing, 0 /* configChanges */,
false /* getNonConfigInstance */, "LocalActivityManager::dispatchDestroy");
}
mActivities.clear();
diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
index 8b52242a6b6c..8a4bee98ca87 100644
--- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
@@ -20,6 +20,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.content.res.Configuration;
import android.os.IBinder;
@@ -32,23 +33,24 @@ import java.util.Objects;
* Activity configuration changed callback.
* @hide
*/
-public class ActivityConfigurationChangeItem extends ClientTransactionItem {
+public class ActivityConfigurationChangeItem extends ActivityTransactionItem {
private Configuration mConfiguration;
@Override
public void preExecute(android.app.ClientTransactionHandler client, IBinder token) {
+ final ActivityClientRecord r = getActivityClientRecord(client, token);
// Notify the client of an upcoming change in the token configuration. This ensures that
// batches of config change items only process the newest configuration.
- client.updatePendingActivityConfiguration(token, mConfiguration);
+ client.updatePendingActivityConfiguration(r, mConfiguration);
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
// TODO(lifecycler): detect if PIP or multi-window mode changed and report it here.
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
- client.handleActivityConfigurationChanged(token, mConfiguration, INVALID_DISPLAY);
+ client.handleActivityConfigurationChanged(r, mConfiguration, INVALID_DISPLAY);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -93,7 +95,7 @@ public class ActivityConfigurationChangeItem extends ClientTransactionItem {
mConfiguration = in.readTypedObject(Configuration.CREATOR);
}
- public static final @android.annotation.NonNull Creator<ActivityConfigurationChangeItem> CREATOR =
+ public static final @NonNull Creator<ActivityConfigurationChangeItem> CREATOR =
new Creator<ActivityConfigurationChangeItem>() {
public ActivityConfigurationChangeItem createFromParcel(Parcel in) {
return new ActivityConfigurationChangeItem(in);
diff --git a/core/java/android/app/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
index c9193a9578e7..cadb6606b1be 100644
--- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java
+++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
@@ -25,7 +25,7 @@ import java.lang.annotation.RetentionPolicy;
* Request for lifecycle state that an activity should reach.
* @hide
*/
-public abstract class ActivityLifecycleItem extends ClientTransactionItem {
+public abstract class ActivityLifecycleItem extends ActivityTransactionItem {
@IntDef(prefix = { "UNDEFINED", "PRE_", "ON_" }, value = {
UNDEFINED,
diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
index 9844de7b6e88..87ea3f8db39c 100644
--- a/core/java/android/app/servertransaction/ActivityRelaunchItem.java
+++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java
@@ -18,7 +18,8 @@ package android.app.servertransaction;
import static android.app.ActivityThread.DEBUG_ORDER;
-import android.app.ActivityThread;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ResultInfo;
import android.os.IBinder;
@@ -36,7 +37,7 @@ import java.util.Objects;
* Activity relaunch callback.
* @hide
*/
-public class ActivityRelaunchItem extends ClientTransactionItem {
+public class ActivityRelaunchItem extends ActivityTransactionItem {
private static final String TAG = "ActivityRelaunchItem";
@@ -50,7 +51,7 @@ public class ActivityRelaunchItem extends ClientTransactionItem {
* A record that was properly configured for relaunch. Execution will be cancelled if not
* initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}.
*/
- private ActivityThread.ActivityClientRecord mActivityClientRecord;
+ private ActivityClientRecord mActivityClientRecord;
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
@@ -59,7 +60,7 @@ public class ActivityRelaunchItem extends ClientTransactionItem {
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
if (mActivityClientRecord == null) {
if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled");
@@ -73,7 +74,8 @@ public class ActivityRelaunchItem extends ClientTransactionItem {
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
- client.reportRelaunch(token, pendingActions);
+ final ActivityClientRecord r = getActivityClientRecord(client, token);
+ client.reportRelaunch(r, pendingActions);
}
// ObjectPoolItem implementation
@@ -130,16 +132,16 @@ public class ActivityRelaunchItem extends ClientTransactionItem {
mPreserveWindow = in.readBoolean();
}
- public static final @android.annotation.NonNull Creator<ActivityRelaunchItem> CREATOR =
+ public static final @NonNull Creator<ActivityRelaunchItem> CREATOR =
new Creator<ActivityRelaunchItem>() {
- public ActivityRelaunchItem createFromParcel(Parcel in) {
- return new ActivityRelaunchItem(in);
- }
-
- public ActivityRelaunchItem[] newArray(int size) {
- return new ActivityRelaunchItem[size];
- }
- };
+ public ActivityRelaunchItem createFromParcel(Parcel in) {
+ return new ActivityRelaunchItem(in);
+ }
+
+ public ActivityRelaunchItem[] newArray(int size) {
+ return new ActivityRelaunchItem[size];
+ }
+ };
@Override
public boolean equals(Object o) {
diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java
index 4e743caccad6..47096a8257e9 100644
--- a/core/java/android/app/servertransaction/ActivityResultItem.java
+++ b/core/java/android/app/servertransaction/ActivityResultItem.java
@@ -18,10 +18,11 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ResultInfo;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Trace;
@@ -33,7 +34,7 @@ import java.util.Objects;
* Activity result delivery callback.
* @hide
*/
-public class ActivityResultItem extends ClientTransactionItem {
+public class ActivityResultItem extends ActivityTransactionItem {
@UnsupportedAppUsage
private List<ResultInfo> mResultInfoList;
@@ -45,10 +46,10 @@ public class ActivityResultItem extends ClientTransactionItem {
}*/
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
- client.handleSendResult(token, mResultInfoList, "ACTIVITY_RESULT");
+ client.handleSendResult(r, mResultInfoList, "ACTIVITY_RESULT");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -88,7 +89,7 @@ public class ActivityResultItem extends ClientTransactionItem {
mResultInfoList = in.createTypedArrayList(ResultInfo.CREATOR);
}
- public static final @android.annotation.NonNull Parcelable.Creator<ActivityResultItem> CREATOR =
+ public static final @NonNull Parcelable.Creator<ActivityResultItem> CREATOR =
new Parcelable.Creator<ActivityResultItem>() {
public ActivityResultItem createFromParcel(Parcel in) {
return new ActivityResultItem(in);
diff --git a/core/java/android/app/servertransaction/ActivityTransactionItem.java b/core/java/android/app/servertransaction/ActivityTransactionItem.java
new file mode 100644
index 000000000000..f7d7e9d20ab9
--- /dev/null
+++ b/core/java/android/app/servertransaction/ActivityTransactionItem.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.app.servertransaction;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
+import android.app.ClientTransactionHandler;
+import android.os.IBinder;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * An activity-targeting callback message to a client that can be scheduled and executed.
+ * It also provides nullity-free version of
+ * {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)} for child class
+ * to inherit.
+ *
+ * @see ClientTransaction
+ * @see ClientTransactionItem
+ * @see com.android.server.wm.ClientLifecycleManager
+ * @hide
+ */
+public abstract class ActivityTransactionItem extends ClientTransactionItem {
+ @Override
+ public final void execute(ClientTransactionHandler client, IBinder token,
+ PendingTransactionActions pendingActions) {
+ final ActivityClientRecord r = getActivityClientRecord(client, token);
+
+ execute(client, r, pendingActions);
+ }
+
+ /**
+ * Like {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)},
+ * but take non-null {@link ActivityClientRecord} as a parameter.
+ */
+ @VisibleForTesting(visibility = PACKAGE)
+ public abstract void execute(@NonNull ClientTransactionHandler client,
+ @NonNull ActivityClientRecord r, PendingTransactionActions pendingActions);
+
+ @NonNull ActivityClientRecord getActivityClientRecord(
+ @NonNull ClientTransactionHandler client, IBinder token) {
+ final ActivityClientRecord r = client.getActivityClient(token);
+ if (r == null) {
+ throw new IllegalArgumentException("Activity client record must not be null to execute "
+ + "transaction item");
+ }
+ if (client.getActivity(token) == null) {
+ throw new IllegalArgumentException("Activity must not be null to execute "
+ + "transaction item");
+ }
+ return r;
+ }
+}
diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java
index 3ee761477efd..1611369497e9 100644
--- a/core/java/android/app/servertransaction/DestroyActivityItem.java
+++ b/core/java/android/app/servertransaction/DestroyActivityItem.java
@@ -18,6 +18,8 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.os.Parcel;
@@ -38,10 +40,10 @@ public class DestroyActivityItem extends ActivityLifecycleItem {
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
- client.handleDestroyActivity(token, mFinished, mConfigChanges,
+ client.handleDestroyActivity(r, mFinished, mConfigChanges,
false /* getNonConfigInstance */, "DestroyActivityItem");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -92,7 +94,7 @@ public class DestroyActivityItem extends ActivityLifecycleItem {
mConfigChanges = in.readInt();
}
- public static final @android.annotation.NonNull Creator<DestroyActivityItem> CREATOR =
+ public static final @NonNull Creator<DestroyActivityItem> CREATOR =
new Creator<DestroyActivityItem>() {
public DestroyActivityItem createFromParcel(Parcel in) {
return new DestroyActivityItem(in);
diff --git a/core/java/android/app/servertransaction/EnterPipRequestedItem.java b/core/java/android/app/servertransaction/EnterPipRequestedItem.java
index b2a1276fa178..b7e81a56afad 100644
--- a/core/java/android/app/servertransaction/EnterPipRequestedItem.java
+++ b/core/java/android/app/servertransaction/EnterPipRequestedItem.java
@@ -16,20 +16,20 @@
package android.app.servertransaction;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
-import android.os.IBinder;
import android.os.Parcel;
/**
* Request an activity to enter picture-in-picture mode.
* @hide
*/
-public final class EnterPipRequestedItem extends ClientTransactionItem {
+public final class EnterPipRequestedItem extends ActivityTransactionItem {
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
- client.handlePictureInPictureRequested(token);
+ client.handlePictureInPictureRequested(r);
}
// ObjectPoolItem implementation
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 2e7b6262c785..77457af77340 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -18,6 +18,7 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ProfilerInfo;
@@ -163,7 +164,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.readTypedObject(FixedRotationAdjustments.CREATOR));
}
- public static final @android.annotation.NonNull Creator<LaunchActivityItem> CREATOR =
+ public static final @NonNull Creator<LaunchActivityItem> CREATOR =
new Creator<LaunchActivityItem>() {
public LaunchActivityItem createFromParcel(Parcel in) {
return new LaunchActivityItem(in);
diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java
index 9a457a3aad40..32de53f189b0 100644
--- a/core/java/android/app/servertransaction/MoveToDisplayItem.java
+++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java
@@ -19,6 +19,7 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.content.res.Configuration;
import android.os.IBinder;
@@ -31,23 +32,24 @@ import java.util.Objects;
* Activity move to a different display message.
* @hide
*/
-public class MoveToDisplayItem extends ClientTransactionItem {
+public class MoveToDisplayItem extends ActivityTransactionItem {
private int mTargetDisplayId;
private Configuration mConfiguration;
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
+ final ActivityClientRecord r = getActivityClientRecord(client, token);
// Notify the client of an upcoming change in the token configuration. This ensures that
// batches of config change items only process the newest configuration.
- client.updatePendingActivityConfiguration(token, mConfiguration);
+ client.updatePendingActivityConfiguration(r, mConfiguration);
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityMovedToDisplay");
- client.handleActivityConfigurationChanged(token, mConfiguration, mTargetDisplayId);
+ client.handleActivityConfigurationChanged(r, mConfiguration, mTargetDisplayId);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -96,7 +98,8 @@ public class MoveToDisplayItem extends ClientTransactionItem {
mConfiguration = in.readTypedObject(Configuration.CREATOR);
}
- public static final @android.annotation.NonNull Creator<MoveToDisplayItem> CREATOR = new Creator<MoveToDisplayItem>() {
+ public static final @NonNull Creator<MoveToDisplayItem> CREATOR =
+ new Creator<MoveToDisplayItem>() {
public MoveToDisplayItem createFromParcel(Parcel in) {
return new MoveToDisplayItem(in);
}
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index 6a4996da38ca..b4e2a7bfa10f 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -19,9 +19,10 @@ package android.app.servertransaction;
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Trace;
@@ -35,7 +36,7 @@ import java.util.Objects;
* New intent message.
* @hide
*/
-public class NewIntentItem extends ClientTransactionItem {
+public class NewIntentItem extends ActivityTransactionItem {
@UnsupportedAppUsage
private List<ReferrerIntent> mIntents;
@@ -47,10 +48,10 @@ public class NewIntentItem extends ClientTransactionItem {
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
- client.handleNewIntent(token, mIntents);
+ client.handleNewIntent(r, mIntents);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -94,7 +95,7 @@ public class NewIntentItem extends ClientTransactionItem {
mIntents = in.createTypedArrayList(ReferrerIntent.CREATOR);
}
- public static final @android.annotation.NonNull Parcelable.Creator<NewIntentItem> CREATOR =
+ public static final @NonNull Parcelable.Creator<NewIntentItem> CREATOR =
new Parcelable.Creator<NewIntentItem>() {
public NewIntentItem createFromParcel(Parcel in) {
return new NewIntentItem(in);
diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java
index f65c843ee76f..cb154e9585e6 100644
--- a/core/java/android/app/servertransaction/PauseActivityItem.java
+++ b/core/java/android/app/servertransaction/PauseActivityItem.java
@@ -18,8 +18,9 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import android.app.ActivityManager;
+import android.annotation.NonNull;
import android.app.ActivityTaskManager;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.os.Parcel;
@@ -40,10 +41,10 @@ public class PauseActivityItem extends ActivityLifecycleItem {
private boolean mDontReport;
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
- client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
+ client.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -130,7 +131,7 @@ public class PauseActivityItem extends ActivityLifecycleItem {
mDontReport = in.readBoolean();
}
- public static final @android.annotation.NonNull Creator<PauseActivityItem> CREATOR =
+ public static final @NonNull Creator<PauseActivityItem> CREATOR =
new Creator<PauseActivityItem>() {
public PauseActivityItem createFromParcel(Parcel in) {
return new PauseActivityItem(in);
diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java
index 905076b08e69..d2a156c37c90 100644
--- a/core/java/android/app/servertransaction/ResumeActivityItem.java
+++ b/core/java/android/app/servertransaction/ResumeActivityItem.java
@@ -18,8 +18,10 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.os.Parcel;
@@ -46,10 +48,10 @@ public class ResumeActivityItem extends ActivityLifecycleItem {
}
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
- client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
+ client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -128,7 +130,7 @@ public class ResumeActivityItem extends ActivityLifecycleItem {
mIsForward = in.readBoolean();
}
- public static final @android.annotation.NonNull Creator<ResumeActivityItem> CREATOR =
+ public static final @NonNull Creator<ResumeActivityItem> CREATOR =
new Creator<ResumeActivityItem>() {
public ResumeActivityItem createFromParcel(Parcel in) {
return new ResumeActivityItem(in);
diff --git a/core/java/android/app/servertransaction/StartActivityItem.java b/core/java/android/app/servertransaction/StartActivityItem.java
index 4fbe02b9cf76..ae0bd24218fb 100644
--- a/core/java/android/app/servertransaction/StartActivityItem.java
+++ b/core/java/android/app/servertransaction/StartActivityItem.java
@@ -18,8 +18,9 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Trace;
@@ -32,10 +33,10 @@ public class StartActivityItem extends ActivityLifecycleItem {
private static final String TAG = "StartActivityItem";
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "startActivityItem");
- client.handleStartActivity(token, pendingActions);
+ client.handleStartActivity(r, pendingActions);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -79,7 +80,7 @@ public class StartActivityItem extends ActivityLifecycleItem {
// Empty
}
- public static final @android.annotation.NonNull Creator<StartActivityItem> CREATOR =
+ public static final @NonNull Creator<StartActivityItem> CREATOR =
new Creator<StartActivityItem>() {
public StartActivityItem createFromParcel(Parcel in) {
return new StartActivityItem(in);
diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java
index 8668bd49c8f5..7708104da16a 100644
--- a/core/java/android/app/servertransaction/StopActivityItem.java
+++ b/core/java/android/app/servertransaction/StopActivityItem.java
@@ -18,6 +18,8 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.os.Parcel;
@@ -34,10 +36,10 @@ public class StopActivityItem extends ActivityLifecycleItem {
private int mConfigChanges;
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
- client.handleStopActivity(token, mConfigChanges, pendingActions,
+ client.handleStopActivity(r, mConfigChanges, pendingActions,
true /* finalStateRequest */, "STOP_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -93,7 +95,7 @@ public class StopActivityItem extends ActivityLifecycleItem {
mConfigChanges = in.readInt();
}
- public static final @android.annotation.NonNull Creator<StopActivityItem> CREATOR =
+ public static final @NonNull Creator<StopActivityItem> CREATOR =
new Creator<StopActivityItem>() {
public StopActivityItem createFromParcel(Parcel in) {
return new StopActivityItem(in);
diff --git a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java
index c7e4c3641631..345c1dd336ab 100644
--- a/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java
+++ b/core/java/android/app/servertransaction/TopResumedActivityChangeItem.java
@@ -17,7 +17,9 @@ package android.app.servertransaction;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import android.annotation.NonNull;
import android.app.ActivityTaskManager;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.os.IBinder;
import android.os.Parcel;
@@ -28,15 +30,15 @@ import android.os.Trace;
* Top resumed activity changed callback.
* @hide
*/
-public class TopResumedActivityChangeItem extends ClientTransactionItem {
+public class TopResumedActivityChangeItem extends ActivityTransactionItem {
private boolean mOnTop;
@Override
- public void execute(ClientTransactionHandler client, IBinder token,
+ public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "topResumedActivityChangeItem");
- client.handleTopResumedActivityChanged(token, mOnTop, "topResumedActivityChangeItem");
+ client.handleTopResumedActivityChanged(r, mOnTop, "topResumedActivityChangeItem");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -97,16 +99,16 @@ public class TopResumedActivityChangeItem extends ClientTransactionItem {
mOnTop = in.readBoolean();
}
- public static final @android.annotation.NonNull Creator<TopResumedActivityChangeItem> CREATOR =
+ public static final @NonNull Creator<TopResumedActivityChangeItem> CREATOR =
new Creator<TopResumedActivityChangeItem>() {
- public TopResumedActivityChangeItem createFromParcel(Parcel in) {
- return new TopResumedActivityChangeItem(in);
- }
-
- public TopResumedActivityChangeItem[] newArray(int size) {
- return new TopResumedActivityChangeItem[size];
- }
- };
+ public TopResumedActivityChangeItem createFromParcel(Parcel in) {
+ return new TopResumedActivityChangeItem(in);
+ }
+
+ public TopResumedActivityChangeItem[] newArray(int size) {
+ return new TopResumedActivityChangeItem[size];
+ }
+ };
@Override
public boolean equals(Object o) {
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 17fcda587322..3dcf2cb5f13e 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -218,29 +218,29 @@ public class TransactionExecutor {
null /* customIntent */);
break;
case ON_START:
- mTransactionHandler.handleStartActivity(r.token, mPendingActions);
+ mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
case ON_RESUME:
- mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
+ mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
- mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
+ mTransactionHandler.handlePauseActivity(r, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
- mTransactionHandler.handleStopActivity(r.token, 0 /* configChanges */,
+ mTransactionHandler.handleStopActivity(r, 0 /* configChanges */,
mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
- mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
+ mTransactionHandler.handleDestroyActivity(r, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
- mTransactionHandler.performRestartActivity(r.token, false /* start */);
+ mTransactionHandler.performRestartActivity(r, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 38bc79750631..5452f92c929f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5820,10 +5820,19 @@ public abstract class Context {
* {@link #createWindowContext(int, Bundle)} on the returned display Context or use an
* {@link android.app.Activity}.
*
+ * <p>
+ * Note that invoking #createDisplayContext(Display) from an UI context is not regarded
+ * as an UI context. In other words, it is not suggested to access UI components (such as
+ * obtain a {@link WindowManager} by {@link #getSystemService(String)})
+ * from the context created from #createDisplayContext(Display).
+ * </p>
+ *
* @param display A {@link Display} object specifying the display for whose metrics the
* Context's resources should be tailored.
*
* @return A {@link Context} for the display.
+ *
+ * @see #getSystemService(String)
*/
@DisplayContext
public abstract Context createDisplayContext(@NonNull Display display);
diff --git a/core/java/android/content/om/TEST_MAPPING b/core/java/android/content/om/TEST_MAPPING
index d35dfdbf32c8..d8f885439b34 100644
--- a/core/java/android/content/om/TEST_MAPPING
+++ b/core/java/android/content/om/TEST_MAPPING
@@ -21,6 +21,20 @@
"include-filter": "android.appsecurity.cts.OverlayHostTest"
}
]
+ },
+ {
+ "name": "CtsContentTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "include-filter": "android.content.om.cts"
+ }
+ ]
}
]
}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 31c77eeb5424..c2beab507da0 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -831,6 +831,16 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
*/
public static final int CONFIG_WINDOW_CONFIGURATION = 0x20000000;
+ /**
+ * Bit in {@link #configChanges} that indicates that the activity
+ * can itself handle changes to bold text. Set from the
+ * {@link android.R.attr#configChanges} attribute. This is
+ * not a core resource configuration, but a higher-level value, so its
+ * constant starts at the high bits.
+ */
+
+ public static final int CONFIG_FORCE_BOLD_TEXT = 0x10000000;
+
/** @hide
* Unfortunately the constants for config changes in native code are
* different from ActivityInfo. :( Here are the values we should use for the
diff --git a/core/java/android/content/pm/ApkChecksum.java b/core/java/android/content/pm/ApkChecksum.java
index e087c44d1ed1..bf678419cbef 100644
--- a/core/java/android/content/pm/ApkChecksum.java
+++ b/core/java/android/content/pm/ApkChecksum.java
@@ -50,7 +50,11 @@ public final class ApkChecksum implements Parcelable {
*/
private final @NonNull Checksum mChecksum;
/**
- * For Installer-provided checksums, certificate of the Installer/AppStore.
+ * For Installer-provided checksums, package name of the Installer.
+ */
+ private final @Nullable String mSourcePackageName;
+ /**
+ * For Installer-provided checksums, certificate of the Installer.
*/
private final @Nullable byte[] mSourceCertificate;
@@ -61,7 +65,7 @@ public final class ApkChecksum implements Parcelable {
*/
public ApkChecksum(@Nullable String splitName, @Checksum.Kind int kind,
@NonNull byte[] value) {
- this(splitName, new Checksum(kind, value), (byte[]) null);
+ this(splitName, new Checksum(kind, value), (String) null, (byte[]) null);
}
/**
@@ -69,10 +73,10 @@ public final class ApkChecksum implements Parcelable {
*
* @hide
*/
- public ApkChecksum(@Nullable String splitName, @Checksum.Kind int kind,
- @NonNull byte[] value, @Nullable Certificate sourceCertificate)
+ public ApkChecksum(@Nullable String splitName, @Checksum.Kind int kind, @NonNull byte[] value,
+ @Nullable String sourcePackageName, @Nullable Certificate sourceCertificate)
throws CertificateEncodingException {
- this(splitName, new Checksum(kind, value),
+ this(splitName, new Checksum(kind, value), sourcePackageName,
(sourceCertificate != null) ? sourceCertificate.getEncoded() : null);
}
@@ -136,19 +140,23 @@ public final class ApkChecksum implements Parcelable {
* Checksum for which split. Null indicates base.apk.
* @param checksum
* Checksum.
+ * @param sourcePackageName
+ * For Installer-provided checksums, package name of the Installer.
* @param sourceCertificate
- * For Installer-provided checksums, certificate of the Installer/AppStore.
+ * For Installer-provided checksums, certificate of the Installer.
* @hide
*/
@DataClass.Generated.Member
public ApkChecksum(
@Nullable String splitName,
@NonNull Checksum checksum,
+ @Nullable String sourcePackageName,
@Nullable byte[] sourceCertificate) {
this.mSplitName = splitName;
this.mChecksum = checksum;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mChecksum);
+ this.mSourcePackageName = sourcePackageName;
this.mSourceCertificate = sourceCertificate;
// onConstructed(); // You can define this method to get a callback
@@ -162,6 +170,14 @@ public final class ApkChecksum implements Parcelable {
return mSplitName;
}
+ /**
+ * For Installer-provided checksums, package name of the Installer.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getSourcePackageName() {
+ return mSourcePackageName;
+ }
+
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -170,10 +186,12 @@ public final class ApkChecksum implements Parcelable {
byte flg = 0;
if (mSplitName != null) flg |= 0x1;
- if (mSourceCertificate != null) flg |= 0x4;
+ if (mSourcePackageName != null) flg |= 0x4;
+ if (mSourceCertificate != null) flg |= 0x8;
dest.writeByte(flg);
if (mSplitName != null) dest.writeString(mSplitName);
dest.writeTypedObject(mChecksum, flags);
+ if (mSourcePackageName != null) dest.writeString(mSourcePackageName);
if (mSourceCertificate != null) dest.writeByteArray(mSourceCertificate);
}
@@ -191,12 +209,14 @@ public final class ApkChecksum implements Parcelable {
byte flg = in.readByte();
String splitName = (flg & 0x1) == 0 ? null : in.readString();
Checksum checksum = (Checksum) in.readTypedObject(Checksum.CREATOR);
- byte[] sourceCertificate = (flg & 0x4) == 0 ? null : in.createByteArray();
+ String sourcePackageName = (flg & 0x4) == 0 ? null : in.readString();
+ byte[] sourceCertificate = (flg & 0x8) == 0 ? null : in.createByteArray();
this.mSplitName = splitName;
this.mChecksum = checksum;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mChecksum);
+ this.mSourcePackageName = sourcePackageName;
this.mSourceCertificate = sourceCertificate;
// onConstructed(); // You can define this method to get a callback
@@ -217,10 +237,10 @@ public final class ApkChecksum implements Parcelable {
};
@DataClass.Generated(
- time = 1599845645160L,
+ time = 1600407436287L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/content/pm/ApkChecksum.java",
- inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable byte[] mSourceCertificate\npublic @android.content.pm.Checksum.Kind int getKind()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getSourceCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getSourceCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mSourcePackageName\nprivate final @android.annotation.Nullable byte[] mSourceCertificate\npublic @android.content.pm.Checksum.Kind int getKind()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getSourceCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getSourceCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/Checksum.java b/core/java/android/content/pm/Checksum.java
index 123aaddda7ce..10ca5cac5276 100644
--- a/core/java/android/content/pm/Checksum.java
+++ b/core/java/android/content/pm/Checksum.java
@@ -32,14 +32,19 @@ import java.util.List;
*
* @see PackageInstaller.Session#addChecksums(String, List)
*/
-@DataClass(genHiddenConstructor = true, genConstDefs = false)
+@DataClass(genConstDefs = false)
public final class Checksum implements Parcelable {
/**
* Root SHA256 hash of a 4K Merkle tree computed over all file bytes.
* <a href="https://source.android.com/security/apksigning/v4">See APK Signature Scheme V4</a>.
* <a href="https://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git/tree/Documentation/filesystems/fsverity.rst">See fs-verity</a>.
*
+ * Recommended for all new applications.
+ * Can be used by kernel to enforce authenticity and integrity of the APK.
+ * <a href="https://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git/tree/Documentation/filesystems/fsverity.rst#">See fs-verity for details</a>
+ *
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
*/
public static final int WHOLE_MERKLE_ROOT_4K_SHA256 = 0x00000001;
@@ -47,20 +52,31 @@ public final class Checksum implements Parcelable {
* MD5 hash computed over all file bytes.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
+ * @deprecated Use SHA2 family of hashes (SHA256/SHA512) instead.
+ * MD5 is cryptographically broken and unsuitable for further use.
+ * Provided for completeness' sake and to support legacy usecases.
*/
+ @Deprecated
public static final int WHOLE_MD5 = 0x00000002;
/**
* SHA1 hash computed over all file bytes.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
+ * @deprecated Use SHA2 family of hashes (SHA256/SHA512) instead.
+ * SHA1 is broken and should not be used.
+ * Provided for completeness' sake and to support legacy usecases.
*/
+ @Deprecated
public static final int WHOLE_SHA1 = 0x00000004;
/**
* SHA256 hash computed over all file bytes.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
*/
public static final int WHOLE_SHA256 = 0x00000008;
@@ -68,6 +84,7 @@ public final class Checksum implements Parcelable {
* SHA512 hash computed over all file bytes.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
*/
public static final int WHOLE_SHA512 = 0x00000010;
@@ -77,6 +94,7 @@ public final class Checksum implements Parcelable {
* <a href="https://source.android.com/security/apksigning/v2">See APK Signature Scheme V2</a>.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
*/
public static final int PARTIAL_MERKLE_ROOT_1M_SHA256 = 0x00000020;
@@ -86,6 +104,7 @@ public final class Checksum implements Parcelable {
* <a href="https://source.android.com/security/apksigning/v2">See APK Signature Scheme V2</a>.
*
* @see PackageManager#getChecksums
+ * @see PackageInstaller.Session#addChecksums
*/
public static final int PARTIAL_MERKLE_ROOT_1M_SHA512 = 0x00000040;
@@ -113,6 +132,7 @@ public final class Checksum implements Parcelable {
+
// Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
@@ -133,7 +153,6 @@ public final class Checksum implements Parcelable {
* Checksum kind.
* @param value
* Checksum value.
- * @hide
*/
@DataClass.Generated.Member
public Checksum(
@@ -214,10 +233,10 @@ public final class Checksum implements Parcelable {
};
@DataClass.Generated(
- time = 1599845646883L,
+ time = 1600717052366L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/content/pm/Checksum.java",
- inputSignatures = "public static final int WHOLE_MERKLE_ROOT_4K_SHA256\npublic static final int WHOLE_MD5\npublic static final int WHOLE_SHA1\npublic static final int WHOLE_SHA256\npublic static final int WHOLE_SHA512\npublic static final int PARTIAL_MERKLE_ROOT_1M_SHA256\npublic static final int PARTIAL_MERKLE_ROOT_1M_SHA512\nprivate final @android.content.pm.Checksum.Kind int mKind\nprivate final @android.annotation.NonNull byte[] mValue\nclass Checksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genConstDefs=false)")
+ inputSignatures = "public static final int WHOLE_MERKLE_ROOT_4K_SHA256\npublic static final @java.lang.Deprecated int WHOLE_MD5\npublic static final @java.lang.Deprecated int WHOLE_SHA1\npublic static final int WHOLE_SHA256\npublic static final int WHOLE_SHA512\npublic static final int PARTIAL_MERKLE_ROOT_1M_SHA256\npublic static final int PARTIAL_MERKLE_ROOT_1M_SHA512\nprivate final @android.content.pm.Checksum.Kind int mKind\nprivate final @android.annotation.NonNull byte[] mValue\nclass Checksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 75ee9b7943fe..da56abf73516 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1227,7 +1227,10 @@ public class PackageInstaller {
* IntentSender)}.
* @throws SecurityException if called after the session has been
* committed or abandoned.
+ * @deprecated use platform-enforced checksums e.g.
+ * {@link Checksum#WHOLE_MERKLE_ROOT_4K_SHA256}
*/
+ @Deprecated
public void addChecksums(@NonNull String name, @NonNull List<Checksum> checksums)
throws IOException {
Objects.requireNonNull(name);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bbb9ab4a5b10..f0b2329385af 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -7873,6 +7873,9 @@ public abstract class PackageManager {
* - enforced by installer.
* If caller needs a specific checksum kind, they can specify it as required.
*
+ * <b>Caution: Android can not verify installer-provided checksums. Make sure you specify
+ * trusted installers.</b>
+ *
* @param packageName whose checksums to return.
* @param includeSplits whether to include checksums for non-base splits.
* @param required explicitly request the checksum kinds. Will incur significant
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 1c98a1ffcbb6..953400e10e15 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -17,6 +17,20 @@
},
{
"name": "CarrierAppIntegrationTestCases"
+ },
+ {
+ "name": "CtsContentTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "include-filter": "android.content.pm.cts"
+ }
+ ]
}
],
"postsubmit": [
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6407f9b3c1b8..49f81f83c39a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -19,6 +19,7 @@ package android.content.res;
import static android.content.ConfigurationProto.COLOR_MODE;
import static android.content.ConfigurationProto.DENSITY_DPI;
import static android.content.ConfigurationProto.FONT_SCALE;
+import static android.content.ConfigurationProto.FORCE_BOLD_TEXT;
import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN;
import static android.content.ConfigurationProto.KEYBOARD;
import static android.content.ConfigurationProto.KEYBOARD_HIDDEN;
@@ -332,6 +333,26 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public int screenLayout;
/**
+ * An undefined forceBoldText.
+ */
+ public static final int FORCE_BOLD_TEXT_UNDEFINED = 0;
+
+ /**
+ * Text is not bold.
+ */
+ public static final int FORCE_BOLD_TEXT_NO = 1;
+
+ /**
+ * Text is bold.
+ */
+ public static final int FORCE_BOLD_TEXT_YES = 2;
+
+ /**
+ * Current user preference for displaying all text in bold.
+ */
+ public int forceBoldText;
+
+ /**
* Configuration relating to the windowing state of the object associated with this
* Configuration. Contents of this field are not intended to affect resources, but need to be
* communicated and propagated at the same time as the rest of Configuration.
@@ -467,6 +488,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if ((diff & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) {
list.add("CONFIG_WINDOW_CONFIGURATION");
}
+ if ((diff & ActivityInfo.CONFIG_FORCE_BOLD_TEXT) != 0) {
+ list.add("CONFIG_AUTO_BOLD_TEXT");
+ }
StringBuilder builder = new StringBuilder("{");
for (int i = 0, n = list.size(); i < n; i++) {
builder.append(list.get(i));
@@ -957,6 +981,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
assetsSeq = o.assetsSeq;
seq = o.seq;
windowConfiguration.setTo(o.windowConfiguration);
+ forceBoldText = o.forceBoldText;
}
public String toString() {
@@ -1112,6 +1137,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (seq != 0) {
sb.append(" s.").append(seq);
}
+ if (forceBoldText != FORCE_BOLD_TEXT_UNDEFINED) {
+ sb.append(" boldText=");
+ sb.append(forceBoldText);
+ } else {
+ sb.append(" ?boldText");
+ }
sb.append('}');
return sb.toString();
}
@@ -1152,6 +1183,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (!persisted && windowConfiguration != null) {
windowConfiguration.dumpDebug(protoOutputStream, WINDOW_CONFIGURATION);
}
+ protoOutputStream.write(FORCE_BOLD_TEXT, forceBoldText);
}
protoOutputStream.write(ORIENTATION, orientation);
protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp);
@@ -1315,6 +1347,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
Slog.e(TAG, "error parsing locale list in configuration.", e);
}
break;
+ case (int) FORCE_BOLD_TEXT:
+ forceBoldText = protoInputStream.readInt(FORCE_BOLD_TEXT);
+ break;
}
}
} finally {
@@ -1410,6 +1445,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
assetsSeq = ASSETS_SEQ_UNDEFINED;
seq = 0;
windowConfiguration.setToDefaults();
+ forceBoldText = FORCE_BOLD_TEXT_UNDEFINED;
}
/**
@@ -1607,6 +1643,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
}
+ if (delta.forceBoldText != FORCE_BOLD_TEXT_UNDEFINED
+ && delta.forceBoldText != forceBoldText) {
+ changed |= ActivityInfo.CONFIG_FORCE_BOLD_TEXT;
+ forceBoldText = delta.forceBoldText;
+ }
+
return changed;
}
@@ -1685,6 +1727,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if ((mask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) {
windowConfiguration.setTo(delta.windowConfiguration, windowMask);
}
+ if ((mask & ActivityInfo.CONFIG_FORCE_BOLD_TEXT) != 0) {
+ forceBoldText = delta.forceBoldText;
+ }
}
/**
@@ -1717,6 +1762,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
* {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
* PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
+ * {@link android.content.pm.ActivityInfo#CONFIG_FORCE_BOLD_TEXT
+ * PackageManager.ActivityInfo.CONFIG_FORCE_BOLD_TEXT.
*/
public int diff(Configuration delta) {
return diff(delta, false /* compareUndefined */, false /* publicOnly */);
@@ -1840,6 +1887,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
}
+ if ((compareUndefined || delta.forceBoldText != FORCE_BOLD_TEXT_UNDEFINED)
+ && forceBoldText != delta.forceBoldText) {
+ changed |= ActivityInfo.CONFIG_FORCE_BOLD_TEXT;
+ }
return changed;
}
@@ -1933,6 +1984,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeValue(windowConfiguration);
dest.writeInt(assetsSeq);
dest.writeInt(seq);
+ dest.writeInt(forceBoldText);
}
public void readFromParcel(Parcel source) {
@@ -1964,6 +2016,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
assetsSeq = source.readInt();
seq = source.readInt();
+ forceBoldText = source.readInt();
}
public static final @android.annotation.NonNull Parcelable.Creator<Configuration> CREATOR
@@ -2062,6 +2115,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (n != 0) return n;
n = windowConfiguration.compareTo(that.windowConfiguration);
if (n != 0) return n;
+ n = this.forceBoldText - that.forceBoldText;
+ if (n != 0) return n;
// if (n != 0) return n;
return n;
@@ -2102,6 +2157,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
result = 31 * result + smallestScreenWidthDp;
result = 31 * result + densityDpi;
result = 31 * result + assetsSeq;
+ result = 31 * result + forceBoldText;
return result;
}
@@ -2674,6 +2730,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (!base.windowConfiguration.equals(change.windowConfiguration)) {
delta.windowConfiguration.setTo(change.windowConfiguration);
}
+
+ if (base.forceBoldText != change.forceBoldText) {
+ delta.forceBoldText = change.forceBoldText;
+ }
return delta;
}
@@ -2697,6 +2757,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
private static final String XML_ATTR_DENSITY = "density";
private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
+ private static final String XML_ATTR_FORCE_BOLD_TEXT = "forceBoldText";
/**
* Reads the attributes corresponding to Configuration member fields from the Xml parser.
@@ -2746,6 +2807,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
DENSITY_DPI_UNDEFINED);
+ configOut.forceBoldText = XmlUtils.readIntAttribute(parser, XML_ATTR_FORCE_BOLD_TEXT,
+ FORCE_BOLD_TEXT_UNDEFINED);
// For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
// out.
diff --git a/core/java/android/content/res/TEST_MAPPING b/core/java/android/content/res/TEST_MAPPING
index 9ebc9969a730..c02af59ab72e 100644
--- a/core/java/android/content/res/TEST_MAPPING
+++ b/core/java/android/content/res/TEST_MAPPING
@@ -2,6 +2,20 @@
"presubmit": [
{
"name": "CtsResourcesLoaderTests"
+ },
+ {
+ "name": "CtsContentTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "include-filter": "android.content.res.cts"
+ }
+ ]
}
]
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 392f56212058..8f99edf61ece 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -841,6 +841,30 @@ public final class DisplayManager {
}
/**
+ * When enabled the app requested mode is always selected regardless of user settings and
+ * policies for low brightness, low battery, etc.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
+ public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
+ mGlobal.setShouldAlwaysRespectAppRequestedMode(enabled);
+ }
+
+ /**
+ * Returns whether we are running in a mode which always selects the app requested display mode
+ * and ignores user settings and policies for low brightness, low battery etc.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
+ public boolean shouldAlwaysRespectAppRequestedMode() {
+ return mGlobal.shouldAlwaysRespectAppRequestedMode();
+ }
+
+ /**
* Listens for changes in available display devices.
*/
public interface DisplayListener {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 0f9c7088a1d0..b046d1df5b8c 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -699,6 +699,32 @@ public final class DisplayManagerGlobal {
}
}
+ /**
+ * When enabled the app requested display resolution and refresh rate is always selected
+ * in DisplayModeDirector regardless of user settings and policies for low brightness, low
+ * battery etc.
+ */
+ public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
+ try {
+ mDm.setShouldAlwaysRespectAppRequestedMode(enabled);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether DisplayModeDirector is running in a mode which always selects the app
+ * requested display mode and ignores user settings and policies for low brightness, low
+ * battery etc.
+ */
+ public boolean shouldAlwaysRespectAppRequestedMode() {
+ try {
+ return mDm.shouldAlwaysRespectAppRequestedMode();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
public void onDisplayEvent(int displayId, int event) {
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index c697106d0c17..85da6424377a 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -128,4 +128,10 @@ interface IDisplayManager {
// The wide gamut color space is returned from composition pipeline
// based on hardware capability.
int getPreferredWideGamutColorSpaceId();
+
+ // When enabled the app requested display resolution and refresh rate is always selected
+ // in DisplayModeDirector regardless of user settings and policies for low brightness, low
+ // battery etc.
+ void setShouldAlwaysRespectAppRequestedMode(boolean enabled);
+ boolean shouldAlwaysRespectAppRequestedMode();
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 80f35a0a2e32..0f1c2a59965b 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -16,6 +16,9 @@
package android.hardware.soundtrigger;
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.RECORD_AUDIO;
+import static android.Manifest.permission.SOUNDTRIGGER_DELEGATE_IDENTITY;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.ENODEV;
import static android.system.OsConstants.ENOSYS;
@@ -27,6 +30,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -34,9 +38,13 @@ import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioFormat;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.Identity;
+import android.media.permission.SafeCloseable;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
import android.media.soundtrigger_middleware.Status;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -1943,16 +1951,6 @@ public class SoundTrigger {
public static final int SERVICE_STATE_DISABLED = 1;
private static Object mServiceLock = new Object();
private static ISoundTriggerMiddlewareService mService;
- /**
- * @return returns current package name.
- */
- static String getCurrentOpPackageName() {
- String packageName = ActivityThread.currentOpPackageName();
- if (packageName == null) {
- return "";
- }
- return packageName;
- }
/**
* Translate an exception thrown from interaction with the underlying service to an error code.
@@ -2005,17 +2003,81 @@ public class SoundTrigger {
* - {@link #STATUS_BAD_VALUE} if modules is null
* - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
*
+ * @deprecated Please use {@link #listModulesAsOriginator(ArrayList, Identity)} or
+ * {@link #listModulesAsMiddleman(ArrayList, Identity, Identity)}, based on whether the
+ * client is acting on behalf of its own identity or a separate identity.
* @hide
*/
@UnsupportedAppUsage
public static int listModules(@NonNull ArrayList<ModuleProperties> modules) {
+ // TODO(ytai): This is a temporary hack to retain prior behavior, which makes
+ // assumptions about process affinity and Binder context, namely that the binder calling ID
+ // reliably reflects the originator identity.
+ Identity middlemanIdentity = new Identity();
+ middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
+
+ Identity originatorIdentity = new Identity();
+ originatorIdentity.pid = Binder.getCallingPid();
+ originatorIdentity.uid = Binder.getCallingUid();
+
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return listModulesAsMiddleman(modules, middlemanIdentity, originatorIdentity);
+ }
+ }
+
+ /**
+ * Returns a list of descriptors for all hardware modules loaded.
+ * This variant is intended for use when the caller itself is the originator of the operation.
+ * @param modules A ModuleProperties array where the list will be returned.
+ * @param originatorIdentity The identity of the originator, which will be used for permission
+ * purposes.
+ * @return - {@link #STATUS_OK} in case of success
+ * - {@link #STATUS_ERROR} in case of unspecified error
+ * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
+ * - {@link #STATUS_NO_INIT} if the native service cannot be reached
+ * - {@link #STATUS_BAD_VALUE} if modules is null
+ * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
+ public static int listModulesAsOriginator(@NonNull ArrayList<ModuleProperties> modules,
+ @NonNull Identity originatorIdentity) {
try {
- SoundTriggerModuleDescriptor[] descs = getService().listModules();
- modules.clear();
- modules.ensureCapacity(descs.length);
- for (SoundTriggerModuleDescriptor desc : descs) {
- modules.add(ConversionUtil.aidl2apiModuleDescriptor(desc));
- }
+ SoundTriggerModuleDescriptor[] descs = getService().listModulesAsOriginator(
+ originatorIdentity);
+ convertDescriptorsToModuleProperties(descs, modules);
+ return STATUS_OK;
+ } catch (Exception e) {
+ return handleException(e);
+ }
+ }
+
+ /**
+ * Returns a list of descriptors for all hardware modules loaded.
+ * This variant is intended for use when the caller is acting on behalf of a different identity
+ * for permission purposes.
+ * @param modules A ModuleProperties array where the list will be returned.
+ * @param middlemanIdentity The identity of the caller, acting as middleman.
+ * @param originatorIdentity The identity of the originator, which will be used for permission
+ * purposes.
+ * @return - {@link #STATUS_OK} in case of success
+ * - {@link #STATUS_ERROR} in case of unspecified error
+ * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
+ * - {@link #STATUS_NO_INIT} if the native service cannot be reached
+ * - {@link #STATUS_BAD_VALUE} if modules is null
+ * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
+ *
+ * @hide
+ */
+ @RequiresPermission(SOUNDTRIGGER_DELEGATE_IDENTITY)
+ public static int listModulesAsMiddleman(@NonNull ArrayList<ModuleProperties> modules,
+ @NonNull Identity middlemanIdentity,
+ @NonNull Identity originatorIdentity) {
+ try {
+ SoundTriggerModuleDescriptor[] descs = getService().listModulesAsMiddleman(
+ middlemanIdentity, originatorIdentity);
+ convertDescriptorsToModuleProperties(descs, modules);
return STATUS_OK;
} catch (Exception e) {
return handleException(e);
@@ -2023,6 +2085,22 @@ public class SoundTrigger {
}
/**
+ * Converts an array of SoundTriggerModuleDescriptor into an (existing) ArrayList of
+ * ModuleProperties.
+ * @param descsIn The input descriptors.
+ * @param modulesOut The output list.
+ */
+ private static void convertDescriptorsToModuleProperties(
+ @NonNull SoundTriggerModuleDescriptor[] descsIn,
+ @NonNull ArrayList<ModuleProperties> modulesOut) {
+ modulesOut.clear();
+ modulesOut.ensureCapacity(descsIn.length);
+ for (SoundTriggerModuleDescriptor desc : descsIn) {
+ modulesOut.add(ConversionUtil.aidl2apiModuleDescriptor(desc));
+ }
+ }
+
+ /**
* Get an interface on a hardware module to control sound models and recognition on
* this module.
* @param moduleId Sound module system identifier {@link ModuleProperties#mId}. mandatory.
@@ -2031,15 +2109,85 @@ public class SoundTrigger {
* is OK.
* @return a valid sound module in case of success or null in case of error.
*
+ * @deprecated Please use
+ * {@link #attachModuleAsOriginator(int, StatusListener, Handler, Identity)} or
+ * {@link #attachModuleAsMiddleman(int, StatusListener, Handler, Identity, Identity)}, based
+ * on whether the client is acting on behalf of its own identity or a separate identity.
* @hide
*/
@UnsupportedAppUsage
- public static @NonNull SoundTriggerModule attachModule(int moduleId,
+ private static SoundTriggerModule attachModule(int moduleId,
@NonNull StatusListener listener,
@Nullable Handler handler) {
+ // TODO(ytai): This is a temporary hack to retain prior behavior, which makes
+ // assumptions about process affinity and Binder context, namely that the binder calling ID
+ // reliably reflects the originator identity.
+ Identity middlemanIdentity = new Identity();
+ middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
+
+ Identity originatorIdentity = new Identity();
+ originatorIdentity.pid = Binder.getCallingPid();
+ originatorIdentity.uid = Binder.getCallingUid();
+
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return attachModuleAsMiddleman(moduleId, listener, handler, middlemanIdentity,
+ originatorIdentity);
+ }
+ }
+
+ /**
+ * Get an interface on a hardware module to control sound models and recognition on
+ * this module.
+ * This variant is intended for use when the caller is acting on behalf of a different identity
+ * for permission purposes.
+ * @param moduleId Sound module system identifier {@link ModuleProperties#mId}. mandatory.
+ * @param listener {@link StatusListener} interface. Mandatory.
+ * @param handler the Handler that will receive the callabcks. Can be null if default handler
+ * is OK.
+ * @param middlemanIdentity The identity of the caller, acting as middleman.
+ * @param originatorIdentity The identity of the originator, which will be used for permission
+ * purposes.
+ * @return a valid sound module in case of success or null in case of error.
+ *
+ * @hide
+ */
+ @RequiresPermission(SOUNDTRIGGER_DELEGATE_IDENTITY)
+ public static SoundTriggerModule attachModuleAsMiddleman(int moduleId,
+ @NonNull SoundTrigger.StatusListener listener,
+ @Nullable Handler handler, Identity middlemanIdentity,
+ Identity originatorIdentity) {
+ Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
+ try {
+ return new SoundTriggerModule(getService(), moduleId, listener, looper,
+ middlemanIdentity, originatorIdentity);
+ } catch (Exception e) {
+ Log.e(TAG, "", e);
+ return null;
+ }
+ }
+
+ /**
+ * Get an interface on a hardware module to control sound models and recognition on
+ * this module.
+ * This variant is intended for use when the caller itself is the originator of the operation.
+ * @param moduleId Sound module system identifier {@link ModuleProperties#mId}. mandatory.
+ * @param listener {@link StatusListener} interface. Mandatory.
+ * @param handler the Handler that will receive the callabcks. Can be null if default handler
+ * is OK.
+ * @param originatorIdentity The identity of the originator, which will be used for permission
+ * purposes.
+ * @return a valid sound module in case of success or null in case of error.
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
+ public static SoundTriggerModule attachModuleAsOriginator(int moduleId,
+ @NonNull SoundTrigger.StatusListener listener,
+ @Nullable Handler handler, @NonNull Identity originatorIdentity) {
Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
try {
- return new SoundTriggerModule(getService(), moduleId, listener, looper);
+ return new SoundTriggerModule(getService(), moduleId, listener, looper,
+ originatorIdentity);
} catch (Exception e) {
Log.e(TAG, "", e);
return null;
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index a2a15b30d578..05823bf14b63 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -19,6 +19,9 @@ package android.hardware.soundtrigger;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.Identity;
+import android.media.permission.SafeCloseable;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
@@ -50,12 +53,39 @@ public class SoundTriggerModule {
private EventHandlerDelegate mEventHandlerDelegate;
private ISoundTriggerModule mService;
+ /**
+ * This variant is intended for use when the caller is acting an originator, rather than on
+ * behalf of a different entity, as far as authorization goes.
+ */
SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
- int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper)
+ int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper,
+ @NonNull Identity originatorIdentity)
throws RemoteException {
mId = moduleId;
mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
- mService = service.attach(moduleId, mEventHandlerDelegate);
+
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mService = service.attachAsOriginator(moduleId, originatorIdentity,
+ mEventHandlerDelegate);
+ }
+ mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
+ }
+
+ /**
+ * This variant is intended for use when the caller is acting as a middleman, i.e. on behalf of
+ * a different entity, as far as authorization goes.
+ */
+ SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
+ int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper,
+ @NonNull Identity middlemanIdentity, @NonNull Identity originatorIdentity)
+ throws RemoteException {
+ mId = moduleId;
+ mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
+
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mService = service.attachAsMiddleman(moduleId, middlemanIdentity, originatorIdentity,
+ mEventHandlerDelegate);
+ }
mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 27bb9e20f968..60ddd8ab22a0 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -18,7 +18,6 @@ package android.inputmethodservice;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -2201,22 +2200,15 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
- * Apply the IME visibility in {@link android.view.ImeInsetsSourceConsumer} when
- * {@link ViewRootImpl.sNewInsetsMode} is enabled.
+ * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}.
+ *
* @param setVisible {@code true} to make it visible, false to hide it.
*/
private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) {
- if (!isVisibilityAppliedUsingInsetsConsumer()) {
- return;
- }
mPrivOps.applyImeVisibility(setVisible
? mCurShowInputToken : mCurHideInputToken, setVisible);
}
- private boolean isVisibilityAppliedUsingInsetsConsumer() {
- return ViewRootImpl.sNewInsetsMode > NEW_INSETS_MODE_NONE;
- }
-
private void finishViews(boolean finishingInput) {
if (mInputViewStarted) {
if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
@@ -2241,14 +2233,9 @@ public class InputMethodService extends AbstractInputMethodService {
mWindowVisible = false;
finishViews(false /* finishingInput */);
if (mDecorViewVisible) {
- // When insets API is enabled, it is responsible for client and server side
- // visibility of IME window.
- if (isVisibilityAppliedUsingInsetsConsumer()) {
- if (mInputView != null) {
- mInputView.dispatchWindowVisibilityChanged(View.GONE);
- }
- } else {
- mWindow.hide();
+ // It is responsible for client and server side visibility of IME window.
+ if (mInputView != null) {
+ mInputView.dispatchWindowVisibilityChanged(View.GONE);
}
mDecorViewVisible = false;
onWindowHidden();
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index ad9a16231f78..52475e9cd89d 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -69,7 +69,7 @@ interface IIncrementalService {
/**
* Creates a file under a storage.
*/
- int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params);
+ int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params, in @nullable byte[] content);
/**
* Creates a file under a storage. Content of the file is from a range inside another file.
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index dcbbd712914a..284c2df2ee7b 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -42,6 +42,7 @@ import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
+import java.util.UUID;
/**
* This class manages storage instances used during a package installation session.
@@ -139,7 +140,7 @@ public final class IncrementalFileStorages {
final String apkName = apk.name;
final File targetFile = new File(mStageDir, apkName);
if (!targetFile.exists()) {
- mDefaultStorage.makeFile(apkName, apk.size, null, apk.metadata, apk.signature);
+ mDefaultStorage.makeFile(apkName, apk.size, null, apk.metadata, apk.signature, null);
}
}
@@ -153,6 +154,13 @@ public final class IncrementalFileStorages {
}
/**
+ * Creates file in default storage and sets its content.
+ */
+ public void makeFile(@NonNull String name, @NonNull byte[] content) throws IOException {
+ mDefaultStorage.makeFile(name, content.length, UUID.randomUUID(), null, null, content);
+ }
+
+ /**
* Permanently disables readlogs.
*/
public void disableReadLogs() {
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index f83541293330..a1c3cc697e02 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -170,9 +170,10 @@ public final class IncrementalStorage {
* @param size Size of the new file in bytes.
* @param metadata Metadata bytes.
* @param v4signatureBytes Serialized V4SignatureProto.
+ * @param content Optionally set file content.
*/
public void makeFile(@NonNull String path, long size, @Nullable UUID id,
- @Nullable byte[] metadata, @Nullable byte[] v4signatureBytes)
+ @Nullable byte[] metadata, @Nullable byte[] v4signatureBytes, @Nullable byte[] content)
throws IOException {
try {
if (id == null && metadata == null) {
@@ -184,7 +185,7 @@ public final class IncrementalStorage {
params.metadata = (metadata == null ? new byte[0] : metadata);
params.fileId = idToBytes(id);
params.signature = v4signatureBytes;
- int res = mService.makeFile(mId, path, params);
+ int res = mService.makeFile(mId, path, params, content);
if (res != 0) {
throw new IOException("makeFile() failed with errno " + -res);
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index d80a7e794220..b15109e67086 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -34,6 +34,7 @@ import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.os.Binder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -543,10 +544,15 @@ public final class PermissionManager {
+ permission);
return PackageManager.PERMISSION_DENIED;
}
+ // Clear Binder.callingUid in case this is called inside the system server. See
+ // more extensive comment in checkPackageNamePermissionUncached
+ long token = Binder.clearCallingIdentity();
try {
return am.checkPermission(permission, pid, uid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -679,11 +685,20 @@ public final class PermissionManager {
/* @hide */
private static int checkPackageNamePermissionUncached(
String permName, String pkgName, @UserIdInt int userId) {
+ // Makeing the binder call "checkPermission" usually sets Binder.callingUid to the calling
+ // processes UID. Hence clearing the calling UID is superflous.
+ // If the call is inside the system server though "checkPermission" is not a binder all, it
+ // is only a method call. Hence Binder.callingUid might still be set to the app that called
+ // the system server. This can lead to problems as not every app can check the same
+ // permissions the system server can check.
+ long token = Binder.clearCallingIdentity();
try {
return ActivityThread.getPermissionManager().checkPermission(
permName, pkgName, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 7a03953f2e9b..99ffee3e2ad9 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -84,6 +84,15 @@ public final class DeviceConfig {
"activity_manager_native_boot";
/**
+ * Namespace for AlarmManager configurations.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
+
+ /**
* Namespace for all app compat related features. These features will be applied
* immediately upon change.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 18337b661844..8a5963ed02eb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11808,29 +11808,6 @@ public final class Settings {
public static final String POWER_MANAGER_CONSTANTS = "power_manager_constants";
/**
- * Alarm manager specific settings.
- * This is encoded as a key=value list, separated by commas. Ex:
- *
- * "min_futurity=5000,allow_while_idle_short_time=4500"
- *
- * The following keys are supported:
- *
- * <pre>
- * min_futurity (long)
- * min_interval (long)
- * allow_while_idle_short_time (long)
- * allow_while_idle_long_time (long)
- * allow_while_idle_whitelist_duration (long)
- * </pre>
- *
- * <p>
- * Type: string
- * @hide
- * @see com.android.server.AlarmManagerService.Constants
- */
- public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
-
- /**
* Job scheduler QuotaController specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 6f941121771e..8f8e6cc3d84a 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -16,9 +16,15 @@
package android.service.voice;
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.RECORD_AUDIO;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +38,7 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.media.AudioFormat;
+import android.media.permission.Identity;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
@@ -39,6 +46,7 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -48,7 +56,12 @@ import java.util.Locale;
/**
* A class that lets a VoiceInteractionService implementation interact with
* always-on keyphrase detection APIs.
+ *
+ * @hide
+ * TODO(b/168605867): Once Metalava supports expressing a removed public, but current system API,
+ * mark and track it as such.
*/
+@SystemApi
public class AlwaysOnHotwordDetector {
//---- States of Keyphrase availability. Return codes for onAvailabilityChanged() ----//
/**
@@ -228,6 +241,7 @@ public class AlwaysOnHotwordDetector {
private KeyphraseMetadata mKeyphraseMetadata;
private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
private final IVoiceInteractionManagerService mModelManagementService;
+ private final IVoiceInteractionSoundTriggerSession mSoundTriggerSession;
private final SoundTriggerListener mInternalCallback;
private final Callback mExternalCallback;
private final Object mLock = new Object();
@@ -425,6 +439,14 @@ public class AlwaysOnHotwordDetector {
mHandler = new MyHandler();
mInternalCallback = new SoundTriggerListener(mHandler);
mModelManagementService = modelManagementService;
+ try {
+ Identity identity = new Identity();
+ identity.packageName = ActivityThread.currentOpPackageName();
+ mSoundTriggerSession = mModelManagementService.createSoundTriggerSessionAsOriginator(
+ identity);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
new RefreshAvailabiltyTask().execute();
}
@@ -485,7 +507,7 @@ public class AlwaysOnHotwordDetector {
private int getSupportedAudioCapabilitiesLocked() {
try {
ModuleProperties properties =
- mModelManagementService.getDspModuleProperties();
+ mSoundTriggerSession.getDspModuleProperties();
if (properties != null) {
return properties.getAudioCapabilities();
}
@@ -513,6 +535,7 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");
synchronized (mLock) {
@@ -543,6 +566,7 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
public boolean stopRecognition() {
if (DBG) Slog.d(TAG, "stopRecognition()");
synchronized (mLock) {
@@ -577,6 +601,7 @@ public class AlwaysOnHotwordDetector {
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
* if API is not supported by HAL
*/
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
public int setParameter(@ModelParams int modelParam, int value) {
if (DBG) {
Slog.d(TAG, "setParameter(" + modelParam + ", " + value + ")");
@@ -604,6 +629,7 @@ public class AlwaysOnHotwordDetector {
* @param modelParam {@link ModelParams}
* @return value of parameter
*/
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
public int getParameter(@ModelParams int modelParam) {
if (DBG) {
Slog.d(TAG, "getParameter(" + modelParam + ")");
@@ -628,6 +654,7 @@ public class AlwaysOnHotwordDetector {
* @param modelParam {@link ModelParams}
* @return supported range of parameter, null if not supported
*/
+ @RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
@Nullable
public ModelParamRange queryParameter(@ModelParams int modelParam) {
if (DBG) {
@@ -658,6 +685,7 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ @Nullable
public Intent createEnrollIntent() {
if (DBG) Slog.d(TAG, "createEnrollIntent");
synchronized (mLock) {
@@ -679,6 +707,7 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ @Nullable
public Intent createUnEnrollIntent() {
if (DBG) Slog.d(TAG, "createUnEnrollIntent");
synchronized (mLock) {
@@ -700,6 +729,7 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ @Nullable
public Intent createReEnrollIntent() {
if (DBG) Slog.d(TAG, "createReEnrollIntent");
synchronized (mLock) {
@@ -782,7 +812,7 @@ public class AlwaysOnHotwordDetector {
int code;
try {
- code = mModelManagementService.startRecognition(
+ code = mSoundTriggerSession.startRecognition(
mKeyphraseMetadata.getId(), mLocale.toLanguageTag(), mInternalCallback,
new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
recognitionExtra, null /* additional data */, audioCapabilities));
@@ -799,7 +829,7 @@ public class AlwaysOnHotwordDetector {
private int stopRecognitionLocked() {
int code;
try {
- code = mModelManagementService.stopRecognition(mKeyphraseMetadata.getId(),
+ code = mSoundTriggerSession.stopRecognition(mKeyphraseMetadata.getId(),
mInternalCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -813,7 +843,7 @@ public class AlwaysOnHotwordDetector {
private int setParameterLocked(@ModelParams int modelParam, int value) {
try {
- int code = mModelManagementService.setParameter(mKeyphraseMetadata.getId(), modelParam,
+ int code = mSoundTriggerSession.setParameter(mKeyphraseMetadata.getId(), modelParam,
value);
if (code != STATUS_OK) {
@@ -828,7 +858,7 @@ public class AlwaysOnHotwordDetector {
private int getParameterLocked(@ModelParams int modelParam) {
try {
- return mModelManagementService.getParameter(mKeyphraseMetadata.getId(), modelParam);
+ return mSoundTriggerSession.getParameter(mKeyphraseMetadata.getId(), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -838,7 +868,7 @@ public class AlwaysOnHotwordDetector {
private ModelParamRange queryParameterLocked(@ModelParams int modelParam) {
try {
SoundTrigger.ModelParamRange modelParamRange =
- mModelManagementService.queryParameter(mKeyphraseMetadata.getId(), modelParam);
+ mSoundTriggerSession.queryParameter(mKeyphraseMetadata.getId(), modelParam);
if (modelParamRange == null) {
return null;
@@ -972,7 +1002,7 @@ public class AlwaysOnHotwordDetector {
ModuleProperties dspModuleProperties;
try {
dspModuleProperties =
- mModelManagementService.getDspModuleProperties();
+ mSoundTriggerSession.getDspModuleProperties();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 45d3465fdae8..fb03ed45113e 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -20,6 +20,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.Service;
import android.compat.annotation.UnsupportedAppUsage;
@@ -237,9 +238,8 @@ public class VoiceInteractionService extends Service {
/**
* Called during service initialization to tell you when the system is ready
* to receive interaction from it. You should generally do initialization here
- * rather than in {@link #onCreate}. Methods such as {@link #showSession} and
- * {@link #createAlwaysOnHotwordDetector}
- * will not be operational until this point.
+ * rather than in {@link #onCreate}. Methods such as {@link #showSession} will
+ * not be operational until this point.
*/
public void onReady() {
mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
@@ -309,9 +309,15 @@ public class VoiceInteractionService extends Service {
* @param locale The locale for which the enrollment needs to be performed.
* @param callback The callback to notify of detection events.
* @return An always-on hotword detector for the given keyphrase and locale.
+ *
+ * @hide
*/
+ @SystemApi
+ @NonNull
public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
- String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) {
+ @SuppressLint("MissingNullability") String keyphrase, // TODO: annotate nullability properly
+ @SuppressLint({"MissingNullability", "UseIcu"}) Locale locale,
+ @SuppressLint("MissingNullability") AlwaysOnHotwordDetector.Callback callback) {
if (mSystemService == null) {
throw new IllegalStateException("Not available until onReady() is called");
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 609f80253ce6..18c87c092569 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -121,7 +121,7 @@ interface IWindowSession {
* @param childrenOnly Whether to only prepare child windows for replacement
* (for example when main windows are being reused via preservation).
*/
- void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly);
+ oneway void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly);
/**
* Called by a client to report that it ran out of graphics memory.
@@ -134,7 +134,7 @@ interface IWindowSession {
* to optimize compositing of this part of the window.
*/
@UnsupportedAppUsage
- void setTransparentRegion(IWindow window, in Region region);
+ oneway void setTransparentRegion(IWindow window, in Region region);
/**
* Tell the window manager about the content and visible insets of the
@@ -146,7 +146,7 @@ interface IWindowSession {
* frame can receive pointer events, as defined by
* {@link android.view.ViewTreeObserver.InternalInsetsInfo}.
*/
- void setInsets(IWindow window, int touchableInsets, in Rect contentInsets,
+ oneway void setInsets(IWindow window, int touchableInsets, in Rect contentInsets,
in Rect visibleInsets, in Region touchableRegion);
/**
@@ -157,10 +157,10 @@ interface IWindowSession {
* is null if there is no sync required.
*/
@UnsupportedAppUsage
- void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
+ oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
@UnsupportedAppUsage
- void setInTouchMode(boolean showFocus);
+ oneway void setInTouchMode(boolean showFocus);
@UnsupportedAppUsage
boolean getInTouchMode();
@@ -192,24 +192,24 @@ interface IWindowSession {
* consumed is 'true' when the drop was accepted by a valid recipient,
* 'false' otherwise.
*/
- void reportDropResult(IWindow window, boolean consumed);
+ oneway void reportDropResult(IWindow window, boolean consumed);
/**
* Cancel the current drag operation.
* skipAnimation is 'true' when it should skip the drag cancel animation which brings the drag
* shadow image back to the drag start position.
*/
- void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation);
+ oneway void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation);
/**
* Tell the OS that we've just dragged into a View that is willing to accept the drop
*/
- void dragRecipientEntered(IWindow window);
+ oneway void dragRecipientEntered(IWindow window);
/**
* Tell the OS that we've just dragged *off* of a View that was willing to accept the drop
*/
- void dragRecipientExited(IWindow window);
+ oneway void dragRecipientExited(IWindow window);
/**
* For windows with the wallpaper behind them, and the wallpaper is
@@ -230,26 +230,26 @@ interface IWindowSession {
* scaled when setWallpaperZoomOut is called. If set to false, the WallpaperService will
* receive the zoom out value but the surface won't be scaled.
*/
- void setShouldZoomOutWallpaper(IBinder windowToken, boolean shouldZoom);
+ oneway void setShouldZoomOutWallpaper(IBinder windowToken, boolean shouldZoom);
@UnsupportedAppUsage
- void wallpaperOffsetsComplete(IBinder window);
+ oneway void wallpaperOffsetsComplete(IBinder window);
/**
* Apply a raw offset to the wallpaper service when shown behind this window.
*/
- void setWallpaperDisplayOffset(IBinder windowToken, int x, int y);
+ oneway void setWallpaperDisplayOffset(IBinder windowToken, int x, int y);
Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, in Bundle extras, boolean sync);
@UnsupportedAppUsage
- void wallpaperCommandComplete(IBinder window, in Bundle result);
+ oneway void wallpaperCommandComplete(IBinder window, in Bundle result);
/**
* Notifies that a rectangle on the screen has been requested.
*/
- void onRectangleOnScreenRequested(IBinder token, in Rect rectangle);
+ oneway void onRectangleOnScreenRequested(IBinder token, in Rect rectangle);
IWindowId getWindowId(IBinder window);
@@ -276,9 +276,9 @@ interface IWindowSession {
*/
boolean startMovingTask(IWindow window, float startX, float startY);
- void finishMovingTask(IWindow window);
+ oneway void finishMovingTask(IWindow window);
- void updatePointerIcon(IWindow window);
+ oneway void updatePointerIcon(IWindow window);
/**
* Reparent the top layers for a display to the requested SurfaceControl. The display that is
@@ -292,7 +292,7 @@ interface IWindowSession {
* to.
* @param displayId The id of the display to be re-parented.
*/
- void reparentDisplayContent(IWindow window, in SurfaceControl sc, int displayId);
+ oneway void reparentDisplayContent(IWindow window, in SurfaceControl sc, int displayId);
/**
* Update the location of a child display in its parent window. This enables windows in the
@@ -303,14 +303,14 @@ interface IWindowSession {
* @param y The y coordinate in the parent window.
* @param displayId The id of the display to be notified.
*/
- void updateDisplayContentLocation(IWindow window, int x, int y, int displayId);
+ oneway void updateDisplayContentLocation(IWindow window, int x, int y, int displayId);
/**
* Update a tap exclude region identified by provided id in the window. Touches on this region
* will neither be dispatched to this window nor change the focus to this window. Passing an
* invalid region will remove the area from the exclude region of this window.
*/
- void updateTapExcludeRegion(IWindow window, in Region region);
+ oneway void updateTapExcludeRegion(IWindow window, in Region region);
/**
* Called when the client has changed the local insets state, and now the server should reflect
@@ -334,8 +334,8 @@ interface IWindowSession {
/**
* Update the flags on an input channel associated with a particular surface.
*/
- void updateInputChannel(in IBinder channelToken, int displayId, in SurfaceControl surface,
- int flags, int privateFlags, in Region region);
+ oneway void updateInputChannel(in IBinder channelToken, int displayId,
+ in SurfaceControl surface, int flags, int privateFlags, in Region region);
/**
* Transfer window focus to an embedded window if the calling window has focus.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 373a0963dc2f..f462a990e958 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -17,10 +17,6 @@
package android.view;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.displayCutout;
@@ -195,18 +191,6 @@ public class InsetsState implements Parcelable {
continue;
}
- boolean skipNonImeInImeMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME
- && source.getType() != ITYPE_IME;
- boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
- && (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR);
- boolean skipLegacyTypes = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
- && (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR
- || type == ITYPE_IME);
- if (skipSystemBars || skipLegacyTypes || skipNonImeInImeMode) {
- typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible();
- continue;
- }
-
processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap,
typeSideMap, typeVisibilityMap);
@@ -239,8 +223,7 @@ public class InsetsState implements Parcelable {
return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
alwaysConsumeSystemBars, cutout, compatInsetsTypes,
- sNewInsetsMode == NEW_INSETS_MODE_FULL
- && (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0);
+ (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0);
}
public Rect calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) {
@@ -250,9 +233,6 @@ public class InsetsState implements Parcelable {
if (source == null) {
continue;
}
- if (sNewInsetsMode != NEW_INSETS_MODE_FULL && type != ITYPE_IME) {
- continue;
- }
// Ignore everything that's not a system bar or IME.
int publicType = InsetsState.toPublicType(type);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 92a0f633aba0..e7e28ac98234 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,7 +17,6 @@
package android.view;
import static android.content.res.Resources.ID_NULL;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
@@ -5435,8 +5434,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
- sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
- || targetSdkVersion < Build.VERSION_CODES.R;
+ sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
@@ -26263,6 +26261,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * This needs to be a better API before it is exposed. For now, only the root view will get
+ * notified.
+ * @hide
+ */
+ public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
+ }
+
+ /**
* Creates an image that the system displays during the drag and drop
* operation. This is called a &quot;drag shadow&quot;. The default implementation
* for a DragShadowBuilder based on a View returns an image that has exactly the same
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e6f89a761e6b..0bbd8992bc1a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -221,45 +221,6 @@ public final class ViewRootImpl implements ViewParent,
private static final boolean MT_RENDERER_AVAILABLE = true;
/**
- * If set to 2, the view system will switch from using rectangles retrieved from window to
- * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets
- * directly from the full configuration, enabling richer information about the insets state, as
- * well as new APIs to control it frame-by-frame, and synchronize animations with it.
- * <p>
- * Only set this to 2 once the new insets system is productionized and the old APIs are
- * fully migrated over.
- * <p>
- * If set to 1, this will switch to a mode where we only use the new approach for IME, but not
- * for the status/navigation bar.
- */
- private static final String USE_NEW_INSETS_PROPERTY = "persist.debug.new_insets";
-
- /**
- * @see #USE_NEW_INSETS_PROPERTY
- * @hide
- */
- public static final int NEW_INSETS_MODE_NONE = 0;
-
- /**
- * @see #USE_NEW_INSETS_PROPERTY
- * @hide
- */
- public static final int NEW_INSETS_MODE_IME = 1;
-
- /**
- * @see #USE_NEW_INSETS_PROPERTY
- * @hide
- */
- public static final int NEW_INSETS_MODE_FULL = 2;
-
- /**
- * @see #USE_NEW_INSETS_PROPERTY
- * @hide
- */
- public static int sNewInsetsMode =
- SystemProperties.getInt(USE_NEW_INSETS_PROPERTY, NEW_INSETS_MODE_FULL);
-
- /**
* Set this system property to true to force the view hierarchy to render
* at 60 Hz. This can be used to measure the potential framerate.
*/
@@ -454,8 +415,8 @@ public final class ViewRootImpl implements ViewParent,
@UnsupportedAppUsage
final View.AttachInfo mAttachInfo;
final SystemUiVisibilityInfo mCompatibleVisibilityInfo;
- int mDispatchedSystemUiVisibility =
- ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL ? 0 : -1;
+ int mDispatchedSystemUiVisibility;
+ int mDispatchedSystemBarAppearance;
InputQueue.Callback mInputQueueCallback;
InputQueue mInputQueue;
@UnsupportedAppUsage
@@ -1409,6 +1370,10 @@ public final class ViewRootImpl implements ViewParent,
attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
+ // Transfer over appearance and behavior values as they carry current state.
+ attrs.insetsFlags.appearance = mWindowAttributes.insetsFlags.appearance;
+ attrs.insetsFlags.behavior = mWindowAttributes.insetsFlags.behavior;
+
final int changes = mWindowAttributes.copyFrom(attrs);
if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
// Recompute system ui visibility.
@@ -1627,9 +1592,6 @@ public final class ViewRootImpl implements ViewParent,
}
void notifyInsetsChanged() {
- if (sNewInsetsMode == NEW_INSETS_MODE_NONE) {
- return;
- }
mApplyInsetsRequested = true;
requestLayout();
@@ -2063,8 +2025,7 @@ public final class ViewRootImpl implements ViewParent,
*/
void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
boolean hasControl) {
- if ((type != ITYPE_STATUS_BAR && type != ITYPE_NAVIGATION_BAR)
- || ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
+ if (type != ITYPE_STATUS_BAR && type != ITYPE_NAVIGATION_BAR) {
return;
}
final SystemUiVisibilityInfo info = mCompatibleVisibilityInfo;
@@ -2089,14 +2050,6 @@ public final class ViewRootImpl implements ViewParent,
}
private void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) {
- if (mSeq != args.seq && sNewInsetsMode != NEW_INSETS_MODE_FULL) {
- // The sequence has changed, so we need to update our value and make
- // sure to do a traversal afterward so the window manager is given our
- // most recent data.
- mSeq = args.seq;
- mAttachInfo.mForceReportNewAttributes = true;
- scheduleTraversals();
- }
if (mView == null) return;
if (args.localChanges != 0) {
mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
@@ -2112,9 +2065,6 @@ public final class ViewRootImpl implements ViewParent,
@VisibleForTesting
public static void adjustLayoutParamsForCompatibility(WindowManager.LayoutParams inOutParams) {
- if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
- return;
- }
final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
final int flags = inOutParams.flags;
final int type = inOutParams.type;
@@ -2179,9 +2129,6 @@ public final class ViewRootImpl implements ViewParent,
}
private void controlInsetsForCompatibility(WindowManager.LayoutParams params) {
- if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
- return;
- }
final int sysUiVis = params.systemUiVisibility | params.subtreeSystemUiVisibility;
final int flags = params.flags;
final boolean matchParent = params.width == MATCH_PARENT && params.height == MATCH_PARENT;
@@ -2629,6 +2576,10 @@ public final class ViewRootImpl implements ViewParent,
}
adjustLayoutParamsForCompatibility(params);
controlInsetsForCompatibility(params);
+ if (mDispatchedSystemBarAppearance != params.insetsFlags.appearance) {
+ mDispatchedSystemBarAppearance = params.insetsFlags.appearance;
+ mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
+ }
}
if (mFirst || windowShouldResize || viewVisibilityChanged || cutoutChanged || params != null
@@ -3239,14 +3190,12 @@ public final class ViewRootImpl implements ViewParent,
hasWindowFocus = mUpcomingWindowFocus;
inTouchMode = mUpcomingInTouchMode;
}
- if (sNewInsetsMode != NEW_INSETS_MODE_NONE) {
- // TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
- // config changes.
- if (hasWindowFocus) {
- mInsetsController.onWindowFocusGained();
- } else {
- mInsetsController.onWindowFocusLost();
- }
+ // TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
+ // config changes.
+ if (hasWindowFocus) {
+ mInsetsController.onWindowFocusGained();
+ } else {
+ mInsetsController.onWindowFocusLost();
}
if (mAdded) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 5d53ad7ef186..f57ee65948c0 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -19,7 +19,6 @@ package android.view;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -30,7 +29,6 @@ import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
@@ -275,19 +273,10 @@ public final class WindowManagerImpl implements WindowManager {
final Configuration config = mContext.getResources().getConfiguration();
final boolean isScreenRound = config.isScreenRound();
final int windowingMode = config.windowConfiguration.getWindowingMode();
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
- isScreenRound, alwaysConsumeSystemBars, displayCutout.get(),
- SOFT_INPUT_ADJUST_NOTHING, attrs.flags, SYSTEM_UI_FLAG_VISIBLE, attrs.type,
- windowingMode, null /* typeSideMap */);
- } else {
- return new WindowInsets.Builder()
- .setAlwaysConsumeSystemBars(alwaysConsumeSystemBars)
- .setRound(isScreenRound)
- .setSystemWindowInsets(Insets.of(systemWindowInsets))
- .setStableInsets(Insets.of(stableInsets))
- .setDisplayCutout(displayCutout.get()).build();
- }
+ return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
+ isScreenRound, alwaysConsumeSystemBars, displayCutout.get(),
+ SOFT_INPUT_ADJUST_NOTHING, attrs.flags, SYSTEM_UI_FLAG_VISIBLE, attrs.type,
+ windowingMode, null /* typeSideMap */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index f6671d86cf7b..a3c95a916669 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -457,9 +457,7 @@ public final class InputMethodManager {
private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
/**
- * When {@link ViewRootImpl#sNewInsetsMode} is set to
- * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
- * IME visibility and listens for other state changes.
+ * Applies the IME visibility and listens for other state changes.
*/
private ImeInsetsSourceConsumer mImeInsetsConsumer;
diff --git a/core/java/android/window/WindowMetricsHelper.java b/core/java/android/window/WindowMetricsHelper.java
index fb8b27e52be1..170ff6fb1a10 100644
--- a/core/java/android/window/WindowMetricsHelper.java
+++ b/core/java/android/window/WindowMetricsHelper.java
@@ -16,17 +16,13 @@
package android.window;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.navigationBars;
import android.annotation.NonNull;
-import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.Display;
-import android.view.DisplayCutout;
-import android.view.ViewRootImpl;
import android.view.WindowInsets;
import android.view.WindowMetrics;
@@ -46,19 +42,8 @@ public final class WindowMetricsHelper {
public static Rect getBoundsExcludingNavigationBarAndCutout(
@NonNull WindowMetrics windowMetrics) {
final WindowInsets windowInsets = windowMetrics.getWindowInsets();
- Insets insets;
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- insets = windowInsets.getInsetsIgnoringVisibility(navigationBars() | displayCutout());
- } else {
- final Insets stableInsets = windowInsets.getStableInsets();
- insets = Insets.of(stableInsets.left, 0 /* top */, stableInsets.right,
- stableInsets.bottom);
- final DisplayCutout cutout = windowInsets.getDisplayCutout();
- insets = (cutout != null) ? Insets.max(insets, Insets.of(cutout.getSafeInsets()))
- : insets;
- }
final Rect result = new Rect(windowMetrics.getBounds());
- result.inset(insets);
+ result.inset(windowInsets.getInsetsIgnoringVisibility(navigationBars() | displayCutout()));
return result;
}
}
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
index 74bfb963c6b0..f8aac42b8018 100644
--- a/core/java/com/android/internal/app/ISoundTriggerService.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -16,53 +16,45 @@
package com.android.internal.app;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.hardware.soundtrigger.IRecognitionStatusCallback;
-import android.hardware.soundtrigger.SoundTrigger;
-import android.hardware.soundtrigger.ModelParams;
-import android.os.Bundle;
-import android.os.ParcelUuid;
+import android.media.permission.Identity;
+import com.android.internal.app.ISoundTriggerSession;
/**
* Service interface for a generic sound recognition model.
+ *
+ * This interface serves as an entry point to establish a session, associated with a client
+ * identity, which exposes the actual functionality.
+ *
* @hide
*/
interface ISoundTriggerService {
-
- SoundTrigger.GenericSoundModel getSoundModel(in ParcelUuid soundModelId);
-
- void updateSoundModel(in SoundTrigger.GenericSoundModel soundModel);
-
- void deleteSoundModel(in ParcelUuid soundModelId);
-
- int startRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback,
- in SoundTrigger.RecognitionConfig config);
-
- int stopRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
-
- int loadGenericSoundModel(in SoundTrigger.GenericSoundModel soundModel);
- int loadKeyphraseSoundModel(in SoundTrigger.KeyphraseSoundModel soundModel);
-
- int startRecognitionForService(in ParcelUuid soundModelId, in Bundle params,
- in ComponentName callbackIntent,in SoundTrigger.RecognitionConfig config);
-
- int stopRecognitionForService(in ParcelUuid soundModelId);
-
- int unloadSoundModel(in ParcelUuid soundModelId);
-
- /** For both ...Intent and ...Service based usage */
- boolean isRecognitionActive(in ParcelUuid parcelUuid);
-
- int getModelState(in ParcelUuid soundModelId);
-
- @nullable SoundTrigger.ModuleProperties getModuleProperties();
-
- int setParameter(in ParcelUuid soundModelId, in ModelParams modelParam,
- int value);
-
- int getParameter(in ParcelUuid soundModelId, in ModelParams modelParam);
-
- @nullable SoundTrigger.ModelParamRange queryParameter(in ParcelUuid soundModelId,
- in ModelParams modelParam);
+ /**
+ * Creates a new session.
+ *
+ * This version is intended to be used when the caller itself is the originator of the
+ * operations, for authorization purposes.
+ *
+ * The pid/uid fields are ignored and will be replaced by those provided by binder.
+ *
+ * It is good practice to clear the binder calling identity prior to calling this, in case the
+ * caller is ever in the same process as the callee.
+ */
+ ISoundTriggerSession attachAsOriginator(in Identity originatorIdentity);
+
+ /**
+ * Creates a new session.
+ *
+ * This version is intended to be used when the caller is acting on behalf of a separate entity
+ * (the originator) and the sessions operations are to be accounted against that originator for
+ * authorization purposes.
+ *
+ * The caller must hold the SOUNDTRIGGER_DELEGATE_IDENTITY permission in order to be trusted to
+ * provide a reliable originator identity. It should follow the best practices for reliably and
+ * securely verifying the identity of the originator.
+ *
+ * It is good practice to clear the binder calling identity prior to calling this, in case the
+ * caller is ever in the same process as the callee.
+ */
+ ISoundTriggerSession attachAsMiddleman(in Identity middlemanIdentity,
+ in Identity originatorIdentity);
}
diff --git a/core/java/com/android/internal/app/ISoundTriggerSession.aidl b/core/java/com/android/internal/app/ISoundTriggerSession.aidl
new file mode 100644
index 000000000000..ec7d282522c8
--- /dev/null
+++ b/core/java/com/android/internal/app/ISoundTriggerSession.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 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.app;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.ModelParams;
+import android.os.Bundle;
+import android.os.ParcelUuid;
+
+/**
+ * Service interface for a generic sound recognition model.
+ * @hide
+ */
+interface ISoundTriggerSession {
+
+ SoundTrigger.GenericSoundModel getSoundModel(in ParcelUuid soundModelId);
+
+ void updateSoundModel(in SoundTrigger.GenericSoundModel soundModel);
+
+ void deleteSoundModel(in ParcelUuid soundModelId);
+
+ int startRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback,
+ in SoundTrigger.RecognitionConfig config);
+
+ int stopRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
+
+ int loadGenericSoundModel(in SoundTrigger.GenericSoundModel soundModel);
+ int loadKeyphraseSoundModel(in SoundTrigger.KeyphraseSoundModel soundModel);
+
+ int startRecognitionForService(in ParcelUuid soundModelId, in Bundle params,
+ in ComponentName callbackIntent,in SoundTrigger.RecognitionConfig config);
+
+ int stopRecognitionForService(in ParcelUuid soundModelId);
+
+ int unloadSoundModel(in ParcelUuid soundModelId);
+
+ /** For both ...Intent and ...Service based usage */
+ boolean isRecognitionActive(in ParcelUuid parcelUuid);
+
+ int getModelState(in ParcelUuid soundModelId);
+
+ @nullable SoundTrigger.ModuleProperties getModuleProperties();
+
+ int setParameter(in ParcelUuid soundModelId, in ModelParams modelParam,
+ int value);
+
+ int getParameter(in ParcelUuid soundModelId, in ModelParams modelParam);
+
+ @nullable SoundTrigger.ModelParamRange queryParameter(in ParcelUuid soundModelId,
+ in ModelParams modelParam);
+}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 15ba8e8c11f7..49b4cd1e6a73 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -18,6 +18,7 @@ package com.android.internal.app;
import android.content.ComponentName;
import android.content.Intent;
+import android.media.permission.Identity;
import android.os.Bundle;
import android.os.RemoteCallback;
@@ -25,9 +26,8 @@ import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.IVoiceInteractionSessionListener;
-import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
import android.hardware.soundtrigger.KeyphraseMetadata;
-import android.hardware.soundtrigger.ModelParams;
import android.hardware.soundtrigger.SoundTrigger;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
@@ -86,13 +86,6 @@ interface IVoiceInteractionManagerService {
* @RequiresPermission Manifest.permission.MANAGE_VOICE_KEYPHRASES
*/
int deleteKeyphraseSoundModel(int keyphraseId, in String bcp47Locale);
-
- /**
- * Gets the properties of the DSP hardware on this device, null if not present.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- */
- SoundTrigger.ModuleProperties getDspModuleProperties();
/**
* Indicates if there's a keyphrase sound model available for the given keyphrase ID and the
* user ID of the caller.
@@ -116,65 +109,6 @@ interface IVoiceInteractionManagerService {
*/
KeyphraseMetadata getEnrolledKeyphraseMetadata(String keyphrase, String bcp47Locale);
/**
- * Starts a recognition for the given keyphrase.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- */
- int startRecognition(int keyphraseId, in String bcp47Locale,
- in IRecognitionStatusCallback callback,
- in SoundTrigger.RecognitionConfig recognitionConfig);
- /**
- * Stops a recognition for the given keyphrase.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- */
- int stopRecognition(int keyphraseId, in IRecognitionStatusCallback callback);
- /**
- * Set a model specific ModelParams with the given value. This
- * parameter will keep its value for the duration the model is loaded regardless of starting and
- * stopping recognition. Once the model is unloaded, the value will be lost.
- * queryParameter should be checked first before calling this method.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- *
- * @param keyphraseId The unique identifier for the keyphrase.
- * @param modelParam ModelParams
- * @param value Value to set
- * @return - {@link SoundTrigger#STATUS_OK} in case of success
- * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
- * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
- * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
- * if API is not supported by HAL
- */
- int setParameter(int keyphraseId, in ModelParams modelParam, int value);
- /**
- * Get a model specific ModelParams. This parameter will keep its value
- * for the duration the model is loaded regardless of starting and stopping recognition.
- * Once the model is unloaded, the value will be lost. If the value is not set, a default
- * value is returned. See ModelParams for parameter default values.
- * queryParameter should be checked first before calling this method.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- *
- * @param keyphraseId The unique identifier for the keyphrase.
- * @param modelParam ModelParams
- * @return value of parameter
- */
- int getParameter(int keyphraseId, in ModelParams modelParam);
- /**
- * Determine if parameter control is supported for the given model handle.
- * This method should be checked prior to calling setParameter or getParameter.
- * Caller must be the active voice interaction service via
- * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
- *
- * @param keyphraseId The unique identifier for the keyphrase.
- * @param modelParam ModelParams
- * @return supported range of parameter, null if not supported
- */
- @nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
- in ModelParams modelParam);
-
- /**
* @return the component name for the currently active voice interaction service
* @RequiresPermission Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE
*/
@@ -277,4 +211,12 @@ interface IVoiceInteractionManagerService {
*/
void setDisabled(boolean disabled);
+ /**
+ * Creates a session, allowing controlling running sound models on detection hardware.
+ * Caller must provide an identity, used for permission tracking purposes.
+ * The uid/pid elements of the identity will be ignored by the server and replaced with the ones
+ * provided by binder.
+ */
+ IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
+ in Identity originatorIdentity);
}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl b/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl
new file mode 100644
index 000000000000..33aab4132150
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl
@@ -0,0 +1,95 @@
+/*
+ * 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.app;
+
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.ModelParams;
+import android.hardware.soundtrigger.SoundTrigger;
+
+/**
+ * This interface allows performing sound-trigger related operations with the actual sound trigger
+ * hardware.
+ *
+ * Every instance of this interface is associated with a client identity ("originator"), established
+ * upon the creation of the instance and used for permission accounting.
+ */
+interface IVoiceInteractionSoundTriggerSession {
+ /**
+ * Gets the properties of the DSP hardware on this device, null if not present.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ */
+ SoundTrigger.ModuleProperties getDspModuleProperties();
+ /**
+ * Starts a recognition for the given keyphrase.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ */
+ int startRecognition(int keyphraseId, in String bcp47Locale,
+ in IRecognitionStatusCallback callback,
+ in SoundTrigger.RecognitionConfig recognitionConfig);
+ /**
+ * Stops a recognition for the given keyphrase.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ */
+ int stopRecognition(int keyphraseId, in IRecognitionStatusCallback callback);
+ /**
+ * Set a model specific ModelParams with the given value. This
+ * parameter will keep its value for the duration the model is loaded regardless of starting and
+ * stopping recognition. Once the model is unloaded, the value will be lost.
+ * queryParameter should be checked first before calling this method.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ *
+ * @param keyphraseId The unique identifier for the keyphrase.
+ * @param modelParam ModelParams
+ * @param value Value to set
+ * @return - {@link SoundTrigger#STATUS_OK} in case of success
+ * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+ * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
+ * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
+ * if API is not supported by HAL
+ */
+ int setParameter(int keyphraseId, in ModelParams modelParam, int value);
+ /**
+ * Get a model specific ModelParams. This parameter will keep its value
+ * for the duration the model is loaded regardless of starting and stopping recognition.
+ * Once the model is unloaded, the value will be lost. If the value is not set, a default
+ * value is returned. See ModelParams for parameter default values.
+ * queryParameter should be checked first before calling this method.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ *
+ * @param keyphraseId The unique identifier for the keyphrase.
+ * @param modelParam ModelParams
+ * @return value of parameter
+ */
+ int getParameter(int keyphraseId, in ModelParams modelParam);
+ /**
+ * Determine if parameter control is supported for the given model handle.
+ * This method should be checked prior to calling setParameter or getParameter.
+ * Caller must be the active voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ *
+ * @param keyphraseId The unique identifier for the keyphrase.
+ * @param modelParam ModelParams
+ * @return supported range of parameter, null if not supported
+ */
+ @nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
+ in ModelParams modelParam);
+}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a6c3dd1071c9..1f8a829aaacd 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -32,6 +32,8 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.Window.DECOR_CAPTION_SHADE_DARK;
import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -97,6 +99,7 @@ import android.view.Window;
import android.view.WindowCallbacks;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -137,19 +140,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private static final int SCRIM_LIGHT = 0xe6ffffff; // 90% white
public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
- new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ new ColorViewAttributes(FLAG_TRANSLUCENT_STATUS,
Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN, ITYPE_STATUS_BAR);
+ com.android.internal.R.id.statusBarBackground, ITYPE_STATUS_BAR);
public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
- new ColorViewAttributes(
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ new ColorViewAttributes(FLAG_TRANSLUCENT_NAVIGATION,
Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */, ITYPE_NAVIGATION_BAR);
+ com.android.internal.R.id.navigationBarBackground, ITYPE_NAVIGATION_BAR);
// This is used to workaround an issue where the PiP shadow can be transparent if the window
// background is transparent
@@ -1016,6 +1016,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
@Override
+ public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
+ updateColorViews(null /* insets */, true /* animate */);
+ }
+
+ @Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
final WindowManager.LayoutParams attrs = mWindow.getAttributes();
mFloatingInsets.setEmpty();
@@ -1094,6 +1099,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
& FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
mLastWindowFlags = attrs.flags;
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ final @Appearance int appearance = viewRoot != null
+ ? viewRoot.mWindowAttributes.insetsFlags.appearance
+ : controller.getSystemBarsAppearance();
+
if (insets != null) {
final Insets systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars());
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
@@ -1130,8 +1140,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
boolean navBarToRightEdge = isNavBarToRightEdge(mLastBottomInset, mLastRightInset);
boolean navBarToLeftEdge = isNavBarToLeftEdge(mLastBottomInset, mLastLeftInset);
int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset, mLastLeftInset);
- updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
- calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
+ updateColorViewInt(mNavigationColorViewState, calculateNavigationBarColor(appearance),
+ mWindow.mNavigationBarDividerColor, navBarSize,
navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
0 /* sideInset */, animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, controller);
@@ -1139,9 +1149,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mDrawLegacyNavigationBarBackground = mNavigationColorViewState.visible
&& (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) {
- ViewRootImpl vri = getViewRootImpl();
- if (vri != null) {
- vri.requestInvalidateRootRenderNode();
+ if (viewRoot != null) {
+ viewRoot.requestInvalidateRootRenderNode();
}
}
@@ -1151,15 +1160,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
&& mNavigationColorViewState.present;
int statusBarSideInset = statusBarNeedsRightInset ? mLastRightInset
: statusBarNeedsLeftInset ? mLastLeftInset : 0;
- updateColorViewInt(mStatusColorViewState, sysUiVisibility,
- calculateStatusBarColor(), 0, mLastTopInset,
- false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
- animate && !disallowAnimate,
+ int statusBarColor = calculateStatusBarColor(appearance);
+ updateColorViewInt(mStatusColorViewState, statusBarColor, 0,
+ mLastTopInset, false /* matchVertical */, statusBarNeedsLeftInset,
+ statusBarSideInset, animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, controller);
if (mHasCaption) {
- final int captionColor = calculateStatusBarColor();
- mDecorCaptionView.getCaption().setBackgroundColor(captionColor);
+ mDecorCaptionView.getCaption().setBackgroundColor(statusBarColor);
updateDecorCaptionShade();
}
}
@@ -1286,29 +1294,30 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
return mOriginalBackgroundDrawable;
}
- private int calculateStatusBarColor() {
+ private int calculateStatusBarColor(@Appearance int appearance) {
return calculateBarColor(mWindow.getAttributes().flags, FLAG_TRANSLUCENT_STATUS,
mSemiTransparentBarColor, mWindow.mStatusBarColor,
- getWindowSystemUiVisibility(), SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ appearance, APPEARANCE_LIGHT_STATUS_BARS,
mWindow.mEnsureStatusBarContrastWhenTransparent);
}
- private int calculateNavigationBarColor() {
+ private int calculateNavigationBarColor(@Appearance int appearance) {
return calculateBarColor(mWindow.getAttributes().flags, FLAG_TRANSLUCENT_NAVIGATION,
mSemiTransparentBarColor, mWindow.mNavigationBarColor,
- getWindowSystemUiVisibility(), SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ appearance, APPEARANCE_LIGHT_NAVIGATION_BARS,
mWindow.mEnsureNavigationBarContrastWhenTransparent
&& getContext().getResources().getBoolean(R.bool.config_navBarNeedsScrim));
}
public static int calculateBarColor(int flags, int translucentFlag, int semiTransparentBarColor,
- int barColor, int sysuiVis, int lightSysuiFlag, boolean scrimTransparent) {
+ int barColor, @Appearance int appearance, @Appearance int lightAppearanceFlag,
+ boolean scrimTransparent) {
if ((flags & translucentFlag) != 0) {
return semiTransparentBarColor;
} else if ((flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
return Color.BLACK;
} else if (scrimTransparent && Color.alpha(barColor) == 0) {
- boolean light = (sysuiVis & lightSysuiFlag) != 0;
+ boolean light = (appearance & lightAppearanceFlag) != 0;
return light ? SCRIM_LIGHT : semiTransparentBarColor;
} else {
return barColor;
@@ -1327,7 +1336,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
* Update a color view
*
* @param state the color view to update.
- * @param sysUiVis the current systemUiVisibility to apply.
* @param color the current color to apply.
* @param dividerColor the current divider color to apply.
* @param size the current size in the non-parent-matching dimension.
@@ -1336,12 +1344,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
* @param sideMargin sideMargin for the color view.
* @param animate if true, the change will be animated.
*/
- private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
- int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin,
- boolean animate, boolean force, WindowInsetsController controller) {
- state.present = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
- ? state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force)
- : state.attributes.isPresent(
+ private void updateColorViewInt(final ColorViewState state, int color, int dividerColor,
+ int size, boolean verticalBar, boolean seascape, int sideMargin, boolean animate,
+ boolean force, WindowInsetsController controller) {
+ state.present = state.attributes.isPresent(
controller.isRequestedVisible(state.attributes.insetsType),
mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
@@ -2583,37 +2589,25 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
public static class ColorViewAttributes {
final int id;
- final int systemUiHideFlag;
final int translucentFlag;
final int verticalGravity;
final int horizontalGravity;
final int seascapeGravity;
final String transitionName;
- final int hideWindowFlag;
final @InternalInsetsType int insetsType;
- private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
- int horizontalGravity, int seascapeGravity, String transitionName, int id,
- int hideWindowFlag, @InternalInsetsType int insetsType) {
+ private ColorViewAttributes(int translucentFlag, int verticalGravity, int horizontalGravity,
+ int seascapeGravity, String transitionName, int id,
+ @InternalInsetsType int insetsType) {
this.id = id;
- this.systemUiHideFlag = systemUiHideFlag;
this.translucentFlag = translucentFlag;
this.verticalGravity = verticalGravity;
this.horizontalGravity = horizontalGravity;
this.seascapeGravity = seascapeGravity;
this.transitionName = transitionName;
- this.hideWindowFlag = hideWindowFlag;
this.insetsType = insetsType;
}
- // TODO(b/118118435): remove after migration
- public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
- return (sysUiVis & systemUiHideFlag) == 0
- && (windowFlags & hideWindowFlag) == 0
- && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || force);
- }
-
public boolean isPresent(boolean requestedVisible, int windowFlags, boolean force) {
return requestedVisible
&& ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || force);
@@ -2625,12 +2619,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
&& ((windowFlags & translucentFlag) == 0 || force);
}
- // TODO(b/118118435): remove after migration
- public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
- final boolean present = isPresent(sysUiVis, windowFlags, force);
- return isVisible(present, color, windowFlags, force);
- }
-
public boolean isVisible(InsetsState state, int color, int windowFlags, boolean force) {
final boolean present = isPresent(state.getSource(insetsType).isVisible(), windowFlags,
force);
diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto
index 7fa0ff64f8bf..d578414eb177 100644
--- a/core/proto/android/content/configuration.proto
+++ b/core/proto/android/content/configuration.proto
@@ -49,6 +49,7 @@ message ConfigurationProto {
optional uint32 density_dpi = 18;
optional .android.app.WindowConfigurationProto window_configuration = 19;
optional string locale_list = 20;
+ optional uint32 force_bold_text = 21;
}
/**
diff --git a/core/proto/android/providers/settings/config.proto b/core/proto/android/providers/settings/config.proto
index d433c0e1859d..f343c3a30927 100644
--- a/core/proto/android/providers/settings/config.proto
+++ b/core/proto/android/providers/settings/config.proto
@@ -29,6 +29,7 @@ message ConfigSettingsProto {
repeated NamespaceProto extra_namespaces = 2;
repeated SettingProto activity_manager_native_boot_settings = 3;
repeated SettingProto activity_manager_settings = 4;
+ repeated SettingProto alarm_manager_settings = 26;
repeated SettingProto app_compat_settings = 5;
repeated SettingProto autofill_settings = 6;
repeated SettingProto blobstore_settings = 23;
@@ -51,10 +52,10 @@ message ConfigSettingsProto {
repeated SettingProto telephony_settings = 21;
repeated SettingProto textclassifier_settings = 22;
- // Next tag: 26
+ // Next tag: 27
message NamespaceProto {
optional string namespace = 1;
repeated SettingProto settings = 2;
}
-} \ No newline at end of file
+}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 3ec14c01c363..50912702e3d6 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -47,7 +47,7 @@ message GlobalSettingsProto {
}
optional AirplaneMode airplane_mode = 5;
- optional SettingProto alarm_manager_constants = 6;
+ reserved 6; // alarm_manager_constants
optional SettingProto allow_user_switching_when_system_user_locked = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
// This is a key=value list, separated by commas.
optional SettingProto always_on_display_constants = 8;
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 7f743ef037a2..5f590be72f52 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -518,11 +518,11 @@ message SecureSettingsProto {
}
optional Sounds sounds = 72;
+ optional SettingProto swipe_bottom_to_notification_enabled = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Defines whether managed profile ringtones should be synced from its
// parent profile.
optional SettingProto sync_parent_sounds = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto system_navigation_keys_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto swipe_bottom_to_notification_enabled = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto theme_customization_overlay_packages = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto trust_agents_initialized = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c9a4ab081a5b..258a050b21af 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3914,6 +3914,14 @@
<permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"
android:protectionLevel="signature" />
+ <!-- Allows an application to override the display mode requests
+ so the app requested mode will be selected and user settings and display
+ policies will be ignored.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to control VPN.
<p>Not for use by third-party applications.</p>
@hide -->
@@ -3976,6 +3984,15 @@
<permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
android:protectionLevel="signature|privileged" />
+ <!-- Puts an application in the chain of trust for sound trigger
+ operations. Being in the chain of trust allows an application to
+ delegate an identity of a separate entity to the sound trigger system
+ and vouch for the authenticity of this identity.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.SOUNDTRIGGER_DELEGATE_IDENTITY"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
<p>Not for use by third-party applications.</p>
@hide -->
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b1183689c5ee..bea18616cba9 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1219,7 +1219,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>
@@ -1230,7 +1230,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 f07fea7bcbbe..68323448a44f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1301,7 +1301,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>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 56736c0d6780..08aeacf9307e 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -720,10 +720,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>
@@ -773,14 +773,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>
@@ -803,19 +803,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-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5ffc420b13b4..f11a228ecae8 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1138,7 +1138,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>
@@ -1224,7 +1224,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-in/strings.xml b/core/res/res/values-in/strings.xml
index f4fb83deba39..f6f50402b3ff 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1234,7 +1234,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>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 6d063b647c41..9798cc9db1b8 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>
@@ -2001,7 +2001,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 b9378def3491..a0b8faa12f78 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -2001,7 +2001,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-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 29666a9aa5bd..14cfee028fdc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -934,9 +934,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>
@@ -1104,7 +1104,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>
@@ -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 903ff83a0572..b5560f186e3a 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -899,7 +899,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-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 4f196440334c..7671809ebcc8 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/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index ed159705a7d7..1c71baeaf46a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -361,7 +361,9 @@
package manager. As such, its use is strongly discouraged and may be
removed in a future version of Android. Instead, apps should use proper
communication mechanisms, such as services and content providers,
- to facilitate interoperability between shared components. -->
+ to facilitate interoperability between shared components. Note that
+ existing apps cannot remove this value, as migrating off a
+ shared user ID is not supported. -->
<attr name="sharedUserId" format="string" />
<!-- Specify a label for the shared user UID of this package. This is
@@ -994,6 +996,8 @@
<!-- The font scaling factor has changed, that is the user has
selected a new global font size. -->
<flag name="fontScale" value="0x40000000" />
+ <!-- The user has enabled or disabled displaying all text in bold -->
+ <flag name="forceBoldText" value="0x10000000" />
</attr>
<!-- Indicate that the activity can be launched as the embedded child of another
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 592afa7012b5..89e348ab57b3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3436,7 +3436,7 @@
<string name="config_emergency_call_number" translatable="false">112</string>
<!-- Package name that provides Emergency Dialer -->
- <string name="config_emergency_dialer_package">com.android.phone</string>
+ <string name="config_emergency_dialer_package" translatable="false">com.android.phone</string>
<!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
affordances-->
@@ -4418,4 +4418,7 @@
<!-- Component names of the services which will keep critical code path warm -->
<string-array name="config_keep_warming_services" translatable="false" />
+
+ <!-- WindowsManager JetPack display features -->
+ <string name="config_display_features" translatable="false" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8cd4b48a0181..996e1f9fde9a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4067,4 +4067,5 @@
<java-symbol type="dimen" name="config_defaultBinderHeavyHitterAutoSamplerThreshold" />
<java-symbol type="array" name="config_keep_warming_services" />
+ <java-symbol type="string" name="config_display_features" />
</resources>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 0a751dd7c66b..23534e2ebebc 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -25,14 +25,14 @@ import static android.view.Display.INVALID_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityThread;
+import android.app.ActivityThread.ActivityClientRecord;
import android.app.IApplicationThread;
import android.app.PictureInPictureParams;
import android.app.ResourcesManager;
@@ -114,11 +114,12 @@ public class ActivityThreadTest {
final ActivityThread activityThread = activity.getActivityThread();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
activityThread.executeTransaction(newResumeTransaction(activity));
- assertNull(activityThread.performResumeActivity(activity.getActivityToken(),
- true /* finalStateRequest */, "test"));
+ final ActivityClientRecord r = getActivityClientRecord(activity);
+ assertFalse(activityThread.performResumeActivity(r, true /* finalStateRequest */,
+ "test"));
- assertNull(activityThread.performResumeActivity(activity.getActivityToken(),
- false /* finalStateRequest */, "test"));
+ assertFalse(activityThread.performResumeActivity(r, false /* finalStateRequest */,
+ "test"));
});
}
@@ -244,20 +245,18 @@ public class ActivityThreadTest {
newerConfig.orientation = orientation == ORIENTATION_LANDSCAPE
? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
newerConfig.seq = seq + 2;
- activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
- newerConfig);
+ final ActivityClientRecord r = getActivityClientRecord(activity);
+ activityThread.updatePendingActivityConfiguration(r, newerConfig);
final Configuration olderConfig = new Configuration();
olderConfig.orientation = orientation;
olderConfig.seq = seq + 1;
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
- olderConfig, INVALID_DISPLAY);
+ activityThread.handleActivityConfigurationChanged(r, olderConfig, INVALID_DISPLAY);
assertEquals(numOfConfig, activity.mNumOfConfigChanges);
assertEquals(olderConfig.orientation, activity.mConfig.orientation);
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
- newerConfig, INVALID_DISPLAY);
+ activityThread.handleActivityConfigurationChanged(r, newerConfig, INVALID_DISPLAY);
assertEquals(numOfConfig + 1, activity.mNumOfConfigChanges);
assertEquals(newerConfig.orientation, activity.mConfig.orientation);
});
@@ -274,7 +273,7 @@ public class ActivityThreadTest {
config.seq = BASE_SEQ;
config.orientation = ORIENTATION_PORTRAIT;
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
+ activityThread.handleActivityConfigurationChanged(getActivityClientRecord(activity),
config, INVALID_DISPLAY);
});
@@ -335,7 +334,7 @@ public class ActivityThreadTest {
config.seq = BASE_SEQ;
config.orientation = ORIENTATION_PORTRAIT;
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
+ activityThread.handleActivityConfigurationChanged(getActivityClientRecord(activity),
config, INVALID_DISPLAY);
});
@@ -472,10 +471,10 @@ public class ActivityThreadTest {
newActivityConfig.orientation = newActivityConfig.orientation == ORIENTATION_PORTRAIT
? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
- activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
- newActivityConfig);
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
- newActivityConfig, INVALID_DISPLAY);
+ final ActivityClientRecord r = getActivityClientRecord(activity);
+ activityThread.updatePendingActivityConfiguration(r, newActivityConfig);
+ activityThread.handleActivityConfigurationChanged(r, newActivityConfig,
+ INVALID_DISPLAY);
assertEquals("Virtual display orientation must not change when activity"
+ " configuration orientation changes.",
@@ -560,9 +559,10 @@ public class ActivityThreadTest {
startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_ENTER, true);
final TestActivity activity = mActivityTestRule.launchActivity(startIntent);
final ActivityThread activityThread = activity.getActivityThread();
+ final ActivityClientRecord r = getActivityClientRecord(activity);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ activityThread.handlePictureInPictureRequested(r);
});
assertTrue(activity.pipRequested());
@@ -575,9 +575,10 @@ public class ActivityThreadTest {
startIntent.putExtra(TestActivity.PIP_REQUESTED_OVERRIDE_SKIP, true);
final TestActivity activity = mActivityTestRule.launchActivity(startIntent);
final ActivityThread activityThread = activity.getActivityThread();
+ final ActivityClientRecord r = getActivityClientRecord(activity);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ activityThread.handlePictureInPictureRequested(r);
});
assertTrue(activity.pipRequested());
@@ -588,9 +589,10 @@ public class ActivityThreadTest {
public void testHandlePictureInPictureRequested_notOverridden() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
final ActivityThread activityThread = activity.getActivityThread();
+ final ActivityClientRecord r = getActivityClientRecord(activity);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- activityThread.handlePictureInPictureRequested(activity.getActivityToken());
+ activityThread.handlePictureInPictureRequested(r);
});
assertTrue(activity.pipRequested());
@@ -599,8 +601,9 @@ public class ActivityThreadTest {
}
/**
- * Calls {@link ActivityThread#handleActivityConfigurationChanged(IBinder, Configuration, int)}
- * to try to push activity configuration to the activity for the given sequence number.
+ * Calls {@link ActivityThread#handleActivityConfigurationChanged(ActivityClientRecord,
+ * Configuration, int)} to try to push activity configuration to the activity for the given
+ * sequence number.
* <p>
* It uses orientation to push the configuration and it tries a different orientation if the
* first attempt doesn't make through, to rule out the possibility that the previous
@@ -613,13 +616,13 @@ public class ActivityThreadTest {
*/
private int applyConfigurationChange(TestActivity activity, int seq) {
final ActivityThread activityThread = activity.getActivityThread();
+ final ActivityClientRecord r = getActivityClientRecord(activity);
final int numOfConfig = activity.mNumOfConfigChanges;
Configuration config = new Configuration();
config.orientation = ORIENTATION_PORTRAIT;
config.seq = seq;
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config,
- INVALID_DISPLAY);
+ activityThread.handleActivityConfigurationChanged(r, config, INVALID_DISPLAY);
if (activity.mNumOfConfigChanges > numOfConfig) {
return config.seq;
@@ -628,12 +631,17 @@ public class ActivityThreadTest {
config = new Configuration();
config.orientation = ORIENTATION_LANDSCAPE;
config.seq = seq + 1;
- activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config,
- INVALID_DISPLAY);
+ activityThread.handleActivityConfigurationChanged(r, config, INVALID_DISPLAY);
return config.seq;
}
+ private static ActivityClientRecord getActivityClientRecord(Activity activity) {
+ final ActivityThread thread = activity.getActivityThread();
+ final IBinder token = activity.getActivityToken();
+ return thread.getActivityClient(token);
+ }
+
private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
null, 0, new MergedConfiguration(), false /* preserveWindow */);
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 3c32c71cf961..0ae789af477c 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -32,11 +32,12 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Activity;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
@@ -225,6 +226,7 @@ public class TransactionExecutorTests {
when(callback2.getPostExecutionState()).thenReturn(UNDEFINED);
ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
IBinder token = mock(IBinder.class);
+ when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
ClientTransaction transaction = ClientTransaction.obtain(null /* client */,
token /* activityToken */);
@@ -236,9 +238,9 @@ public class TransactionExecutorTests {
mExecutor.execute(transaction);
InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2, stateRequest);
- inOrder.verify(callback1, times(1)).execute(eq(mTransactionHandler), eq(token), any());
- inOrder.verify(callback2, times(1)).execute(eq(mTransactionHandler), eq(token), any());
- inOrder.verify(stateRequest, times(1)).execute(eq(mTransactionHandler), eq(token), any());
+ inOrder.verify(callback1).execute(eq(mTransactionHandler), eq(token), any());
+ inOrder.verify(callback2).execute(eq(mTransactionHandler), eq(token), any());
+ inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
}
@Test
@@ -273,7 +275,7 @@ public class TransactionExecutorTests {
// The launch transaction should not be executed because its token is in the
// to-be-destroyed container.
- verify(launchItem, times(0)).execute(any(), any(), any());
+ verify(launchItem, never()).execute(any(), any(), any());
// After the destroy transaction has been executed, the token should be removed.
mExecutor.execute(destroyTransaction);
@@ -282,6 +284,8 @@ public class TransactionExecutorTests {
@Test
public void testActivityResultRequiredStateResolution() {
+ when(mTransactionHandler.getActivity(any())).thenReturn(mock(Activity.class));
+
PostExecItem postExecItem = new PostExecItem(ON_RESUME);
IBinder token = mock(IBinder.class);
@@ -292,12 +296,12 @@ public class TransactionExecutorTests {
// Verify resolution that should get to onPause
mClientRecord.setState(ON_RESUME);
mExecutor.executeCallbacks(transaction);
- verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction));
+ verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_PAUSE), eq(transaction));
// Verify resolution that should get to onStart
mClientRecord.setState(ON_STOP);
mExecutor.executeCallbacks(transaction);
- verify(mExecutor, times(1)).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction));
+ verify(mExecutor).cycleToPath(eq(mClientRecord), eq(ON_START), eq(transaction));
}
@Test
@@ -433,6 +437,36 @@ public class TransactionExecutorTests {
mExecutorHelper.getClosestPreExecutionState(mClientRecord, ON_RESUME));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testActivityItemNullRecordThrowsException() {
+ final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
+ when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
+ final IBinder token = mock(IBinder.class);
+ final ClientTransaction transaction = ClientTransaction.obtain(null /* client */, token);
+ transaction.addCallback(activityItem);
+ when(mTransactionHandler.getActivityClient(token)).thenReturn(null);
+
+ mExecutor.executeCallbacks(transaction);
+ }
+
+ @Test
+ public void testActivityItemExecute() {
+ final IBinder token = mock(IBinder.class);
+ final ClientTransaction transaction = ClientTransaction.obtain(null /* client */, token);
+ final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
+ when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
+ transaction.addCallback(activityItem);
+ final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
+ transaction.setLifecycleStateRequest(stateRequest);
+ when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
+
+ mExecutor.execute(transaction);
+
+ final InOrder inOrder = inOrder(activityItem, stateRequest);
+ inOrder.verify(activityItem).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ }
+
private static int[] shuffledArray(int[] inputArray) {
final List<Integer> list = Arrays.stream(inputArray).boxed().collect(Collectors.toList());
Collections.shuffle(list);
@@ -489,13 +523,13 @@ public class TransactionExecutorTests {
public static final Parcelable.Creator<StubItem> CREATOR =
new Parcelable.Creator<StubItem>() {
- public StubItem createFromParcel(Parcel in) {
- return new StubItem(in);
- }
-
- public StubItem[] newArray(int size) {
- return new StubItem[size];
- }
- };
+ public StubItem createFromParcel(Parcel in) {
+ return new StubItem(in);
+ }
+
+ public StubItem[] newArray(int size) {
+ return new StubItem[size];
+ }
+ };
}
}
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index 777f4a3e03a8..d1776fb7e5c1 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(createUiContext());
assertTrue(wrapper.isUiContext());
}
- private static class TestUiContext extends ContextWrapper {
- TestUiContext() {
- super(null /* base */);
- }
+ @Test
+ public void testIsUiContext_UiContextDerivedContext() {
+ final Context uiContext = createUiContext();
+ 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 = createUiContext();
+ final Display secondaryDisplay =
+ getSecondaryDisplay(uiContext.getSystemService(DisplayManager.class));
+ final Context context = uiContext.createDisplayContext(secondaryDisplay);
+
+ assertFalse(context.isUiContext());
+ }
+
+ private Context createUiContext() {
+ 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/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index a2b1e3d69cd2..8412e53060c7 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -18,7 +18,6 @@ package android.view;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.systemBars;
import static org.junit.Assert.assertEquals;
@@ -42,13 +41,10 @@ import android.util.SparseArray;
import android.view.SurfaceControl.Transaction;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.animation.LinearInterpolator;
-import android.view.test.InsetsModeSession;
import androidx.test.runner.AndroidJUnit4;
-import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -76,22 +72,11 @@ public class InsetsAnimationControlImplTest {
private SurfaceControl mTopLeash;
private SurfaceControl mNavLeash;
private InsetsState mInsetsState;
- private static InsetsModeSession sInsetsModeSession;
@Mock Transaction mMockTransaction;
@Mock InsetsController mMockController;
@Mock WindowInsetsAnimationControlListener mMockListener;
- @BeforeClass
- public static void setupOnce() {
- sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
- }
-
- @AfterClass
- public static void tearDownOnce() {
- sInsetsModeSession.close();
- }
-
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 88e1f5781e0e..cc97eb5988e6 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -26,7 +26,6 @@ import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
@@ -63,7 +62,6 @@ import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
import android.view.WindowManager.BadTokenException;
import android.view.WindowManager.LayoutParams;
import android.view.animation.LinearInterpolator;
-import android.view.test.InsetsModeSession;
import android.widget.TextView;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -72,9 +70,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
-import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -102,17 +98,6 @@ public class InsetsControllerTest {
private TestHost mTestHost;
private TestHandler mTestHandler;
private OffsettableClock mTestClock;
- private static InsetsModeSession sInsetsModeSession;
-
- @BeforeClass
- public static void setupOnce() {
- sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
- }
-
- @AfterClass
- public static void tearDownOnce() {
- sInsetsModeSession.close();
- }
@Before
public void setup() {
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 4306e3e0fe7b..afab7696e87d 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -31,6 +31,7 @@ import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -51,7 +52,6 @@ import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
-import android.view.test.InsetsModeSession;
import androidx.test.runner.AndroidJUnit4;
@@ -75,114 +75,96 @@ public class InsetsStateTest {
private InsetsState mState2 = new InsetsState();
@Test
- public void testCalculateInsets() throws Exception {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
- SparseIntArray typeSideMap = new SparseIntArray();
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, typeSideMap);
- assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
- assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
- assertEquals(ISIDE_BOTTOM, typeSideMap.get(ITYPE_IME));
- assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
- }
+ public void testCalculateInsets() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ SparseIntArray typeSideMap = new SparseIntArray();
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0,
+ TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, typeSideMap);
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
+ assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
+ assertEquals(ISIDE_BOTTOM, typeSideMap.get(ITYPE_IME));
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(ime()));
}
@Test
- public void testCalculateInsets_imeAndNav() throws Exception{
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(100, insets.getStableInsetBottom());
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.navigationBars()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
- }
+ public void testCalculateInsets_imeAndNav() {
+ mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0,
+ TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(100, insets.getStableInsetBottom());
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(systemBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(navigationBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(ime()));
}
@Test
- public void testCalculateInsets_navRightStatusTop() throws Exception {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
- mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
- 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()));
- }
+ public void testCalculateInsets_navRightStatusTop() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION,
+ WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
}
@Test
public void testCalculateInsets_imeIgnoredWithoutAdjustResize() {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(0, insets.getSystemWindowInsetBottom());
- assertEquals(100, insets.getInsets(ime()).bottom);
- assertTrue(insets.isVisible(ime()));
- }
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0,
+ TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(0, insets.getSystemWindowInsetBottom());
+ assertEquals(100, insets.getInsets(ime()).bottom);
+ assertTrue(insets.isVisible(ime()));
}
@Test
public void testCalculateInsets_systemUiFlagLayoutStable() {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
- SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(100, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(0, insets.getSystemWindowInsetTop());
- }
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
+ SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(100, insets.getSystemWindowInsetTop());
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(0, insets.getSystemWindowInsetTop());
}
@Test
public void testCalculateInsets_systemUiFlagLayoutStable_windowFlagFullscreen() {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN,
- SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(0, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
- assertEquals(0, insets.getSystemWindowInsetTop());
- }
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN,
+ SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(0, insets.getSystemWindowInsetTop());
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(0, insets.getSystemWindowInsetTop());
}
@Test
@@ -209,65 +191,53 @@ public class InsetsStateTest {
@Test
- public void testCalculateInsets_captionStatusBarOverlap() throws Exception {
- try (InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
- mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
-
- Rect visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
- assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
- }
+ public void testCalculateInsets_captionStatusBarOverlap() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
}
@Test
- public void testCalculateInsets_captionBarOffset() throws Exception {
- try (InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
- mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
-
- Rect visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
- assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
- }
+ public void testCalculateInsets_captionBarOffset() {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
}
@Test
- public void testCalculateInsets_extraNavRightStatusTop() throws Exception {
- try (InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_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, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
- 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()));
- }
+ public void testCalculateInsets_extraNavRightStatusTop() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_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, TYPE_APPLICATION,
+ WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
}
@Test
- public void testCalculateInsets_navigationRightClimateTop() throws Exception {
- try (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_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
- mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
- 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()));
- }
+ public void testCalculateInsets_navigationRightClimateTop() {
+ mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true);
+ mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION,
+ WINDOWING_MODE_UNDEFINED, null);
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
}
@Test
@@ -371,59 +341,51 @@ public class InsetsStateTest {
}
@Test
- public void testCalculateVisibleInsets() throws Exception {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
-
- // Make sure bottom gestures are ignored
- mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
- mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
- Rect visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_PAN);
- assertEquals(new Rect(0, 100, 0, 100), visibleInsets);
- }
+ public void testCalculateVisibleInsets() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+
+ // Make sure bottom gestures are ignored
+ mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_PAN);
+ assertEquals(new Rect(0, 100, 0, 100), visibleInsets);
}
@Test
- public void testCalculateVisibleInsets_adjustNothing() throws Exception {
- try (final InsetsModeSession session =
- new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
-
- // Make sure bottom gestures are ignored
- mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
- mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
- Rect visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_NOTHING);
- assertEquals(new Rect(0, 100, 0, 0), visibleInsets);
- }
+ public void testCalculateVisibleInsets_adjustNothing() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+
+ // Make sure bottom gestures are ignored
+ mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 100, 0, 0), visibleInsets);
}
@Test
- public void testCalculateUncontrollableInsets() throws Exception {
- try (InsetsModeSession session = new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
- mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 200, 100));
- mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
- mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 200, 300));
- mState.getSource(ITYPE_IME).setVisible(true);
- mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(100, 0, 200, 300));
- mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
-
- mState.setDisplayFrame(new Rect(0, 0, 200, 300));
- assertEquals(0,
- mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 0, 200, 300)));
- assertEquals(statusBars() | ime(),
- mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 50, 200, 250)));
- assertEquals(navigationBars(),
- mState.calculateUncontrollableInsetsFromFrame(new Rect(50, 0, 150, 300)));
- }
+ public void testCalculateUncontrollableInsets() {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 200, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 200, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(100, 0, 200, 300));
+ mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+
+ mState.setDisplayFrame(new Rect(0, 0, 200, 300));
+ assertEquals(0,
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 0, 200, 300)));
+ assertEquals(statusBars() | ime(),
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 50, 200, 250)));
+ assertEquals(navigationBars(),
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(50, 0, 150, 300)));
}
private void assertEqualsAndHashCode() {
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 9d95de7eb60f..5ac610b5140f 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -243,27 +243,27 @@ public class ActivityThreadClientTest {
}
private void startActivity(ActivityClientRecord r) {
- mThread.handleStartActivity(r.token, null /* pendingActions */);
+ mThread.handleStartActivity(r, null /* pendingActions */);
}
private void resumeActivity(ActivityClientRecord r) {
- mThread.handleResumeActivity(r.token, true /* finalStateRequest */,
+ mThread.handleResumeActivity(r, true /* finalStateRequest */,
true /* isForward */, "test");
}
private void pauseActivity(ActivityClientRecord r) {
- mThread.handlePauseActivity(r.token, false /* finished */,
+ mThread.handlePauseActivity(r, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, null /* pendingActions */,
"test");
}
private void stopActivity(ActivityClientRecord r) {
- mThread.handleStopActivity(r.token, 0 /* configChanges */,
+ mThread.handleStopActivity(r, 0 /* configChanges */,
new PendingTransactionActions(), false /* finalStateRequest */, "test");
}
private void destroyActivity(ActivityClientRecord r) {
- mThread.handleDestroyActivity(r.token, true /* finishing */, 0 /* configChanges */,
+ mThread.handleDestroyActivity(r, true /* finishing */, 0 /* configChanges */,
false /* getNonConfigInstance */, "test");
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index dd8f40d586bc..0a0681479278 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -153,8 +153,8 @@
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
<assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="media" />
-
<assign-permission name="android.permission.INTERNET" uid="media" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="media" />
<assign-permission name="android.permission.INTERNET" uid="shell" />
@@ -164,6 +164,7 @@
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="audioserver" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="audioserver" />
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
@@ -174,8 +175,10 @@
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="cameraserver" />
<assign-permission name="android.permission.WATCH_APPOPS" uid="cameraserver" />
<assign-permission name="android.permission.MANAGE_APP_OPS_MODES" uid="cameraserver" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="cameraserver" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="graphics" />
<assign-permission name="android.permission.DUMP" uid="incidentd" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" />
@@ -190,8 +193,10 @@
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
<assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="statsd" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="statsd" />
<assign-permission name="android.permission.REGISTER_STATS_PULL_ATOM" uid="gpu_service" />
+ <assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="gpu_service" />
<split-permission name="android.permission.ACCESS_FINE_LOCATION">
<new-permission name="android.permission.ACCESS_COARSE_LOCATION" />
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 217de84cfc3e..6b80bb60ec67 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -259,6 +259,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "-1741065110": {
+ "message": "No app is requesting an orientation, return %d for display id=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"-1730156332": {
"message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
"level": "VERBOSE",
@@ -1909,6 +1915,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowToken.java"
},
+ "845234215": {
+ "message": "App is requesting an orientation, return %d for display id=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"853091290": {
"message": "Moved stack=%s behind stack=%s",
"level": "DEBUG",
@@ -2179,12 +2191,6 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
},
- "1381227466": {
- "message": "App is requesting an orientation, return %d for display id=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
- },
"1401295262": {
"message": "Mode default, asking user",
"level": "WARN",
@@ -2371,12 +2377,6 @@
"group": "WM_DEBUG_RESIZE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
- "1640436199": {
- "message": "No app is requesting an orientation, return %d for display id=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
- },
"1653210583": {
"message": "Removing app %s delayed=%b animation=%s animating=%b",
"level": "VERBOSE",
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 4c214b529b39..c992bd8f8338 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -142,11 +142,30 @@
<font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
</family>
<family lang="und-Armn">
- <font weight="400" style="normal">NotoSansArmenian-Regular.otf</font>
- <font weight="500" style="normal">NotoSansArmenian-Medium.otf</font>
- <font weight="700" style="normal">NotoSansArmenian-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansArmenian-VF.ttf
+ <axis tag="wght" stylevalue="400" />
+ </font>
+ <font weight="500" style="normal">NotoSansArmenian-VF.ttf
+ <axis tag="wght" stylevalue="500" />
+ </font>
+ <font weight="600" style="normal">NotoSansArmenian-VF.ttf
+ <axis tag="wght" stylevalue="600" />
+ </font>
+ <font weight="700" style="normal">NotoSansArmenian-VF.ttf
+ <axis tag="wght" stylevalue="700" />
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <axis tag="wght" stylevalue="400" />
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <axis tag="wght" stylevalue="500" />
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <axis tag="wght" stylevalue="600" />
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <axis tag="wght" stylevalue="700" />
+ </font>
</family>
<family lang="und-Geor,und-Geok">
<font weight="400" style="normal">NotoSansGeorgian-VF.ttf
diff --git a/data/keyboards/Vendor_27f8_Product_0bbe.kl b/data/keyboards/Vendor_27f8_Product_0bbe.kl
new file mode 100644
index 000000000000..211e532c8326
--- /dev/null
+++ b/data/keyboards/Vendor_27f8_Product_0bbe.kl
@@ -0,0 +1,54 @@
+# 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.
+
+#
+# Gamevice GV186 Mobile Controller
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+key 0x133 BUTTON_X
+key 0x130 BUTTON_A
+key 0x131 BUTTON_B
+key 0x134 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+axis 0x00 X
+axis 0x01 Y
+
+axis 0x02 Z
+axis 0x05 RZ
+
+axis 0x09 RTRIGGER
+axis 0x0a LTRIGGER
+
+key 0x13d BUTTON_THUMBL
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Left Triangle Button
+key 0x13a BUTTON_SELECT
+# Right Triangle Button
+key 0x13b BUTTON_START
+# Home Button
+key 0x13c BUTTON_MODE
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
index ca3a5112bc55..5397302f6882 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
@@ -37,6 +37,8 @@ import android.util.Log;
import androidx.annotation.NonNull;
+import com.android.internal.R;
+
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
@@ -151,13 +153,18 @@ class SettingsSidecarImpl extends StubSidecar {
return features;
}
- ContentResolver resolver = mContext.getContentResolver();
- final String displayFeaturesString = Settings.Global.getString(resolver, DISPLAY_FEATURES);
if (isInMultiWindow(windowToken)) {
// It is recommended not to report any display features in multi-window mode, since it
// won't be possible to synchronize the display feature positions with window movement.
return features;
}
+
+ ContentResolver resolver = mContext.getContentResolver();
+ String displayFeaturesString = Settings.Global.getString(resolver, DISPLAY_FEATURES);
+ if (TextUtils.isEmpty(displayFeaturesString)) {
+ displayFeaturesString = mContext.getResources().getString(
+ R.string.config_display_features);
+ }
if (TextUtils.isEmpty(displayFeaturesString)) {
return features;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 283fd8d997c9..c18e9ce76153 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -178,7 +178,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
- class PerDisplay extends IDisplayWindowInsetsController.Stub {
+ /** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */
+ public class PerDisplay extends IDisplayWindowInsetsController.Stub {
final int mDisplayId;
final InsetsState mInsetsState = new InsetsState();
InsetsSourceControl mImeSourceControl = null;
@@ -189,7 +190,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
final Rect mImeFrame = new Rect();
boolean mAnimateAlpha = true;
- PerDisplay(int displayId, int initialRotation) {
+ public PerDisplay(int displayId, int initialRotation) {
mDisplayId = displayId;
mRotation = initialRotation;
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c7560b2496ef..04359818e1b7 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -139,7 +139,7 @@ void CanvasContext::destroy() {
mAnimationContext->destroy();
}
-static void setBufferCount(ANativeWindow* window, uint32_t extraBuffers) {
+static void setBufferCount(ANativeWindow* window) {
int query_value;
int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
if (err != 0 || query_value < 0) {
@@ -148,7 +148,9 @@ static void setBufferCount(ANativeWindow* window, uint32_t extraBuffers) {
}
auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
- int bufferCount = min_undequeued_buffers + 2 + extraBuffers;
+ // We only need to set min_undequeued + 2 because the renderahead amount was already factored into the
+ // query for min_undequeued
+ int bufferCount = min_undequeued_buffers + 2;
native_window_set_buffer_count(window, bufferCount);
}
@@ -182,7 +184,8 @@ void CanvasContext::setupPipelineSurface() {
mNativeSurface ? mNativeSurface->getNativeWindow() : nullptr, mSwapBehavior);
if (mNativeSurface && !mNativeSurface->didSetExtraBuffers()) {
- setBufferCount(mNativeSurface->getNativeWindow(), mRenderAheadCapacity);
+ setBufferCount(mNativeSurface->getNativeWindow());
+
}
mFrameNumber = -1;
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 0f6dddba842b..6e597b2c1d63 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,6 +20,8 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static android.location.LocationRequest.createFromDeprecatedCriteria;
+import static android.location.LocationRequest.createFromDeprecatedProvider;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
@@ -1027,9 +1029,7 @@ public class LocationManager {
requestLocationUpdates(
provider,
- new LocationRequest.Builder(minTimeMs)
- .setMinUpdateDistanceMeters(minDistanceM)
- .build(),
+ createFromDeprecatedProvider(provider, minTimeMs, minDistanceM, false),
executor,
listener);
}
@@ -1088,10 +1088,7 @@ public class LocationManager {
requestLocationUpdates(
FUSED_PROVIDER,
- new LocationRequest.Builder(minTimeMs)
- .setQuality(criteria)
- .setMinUpdateDistanceMeters(minDistanceM)
- .build(),
+ createFromDeprecatedCriteria(criteria, minTimeMs, minDistanceM, false),
executor,
listener);
}
@@ -1119,9 +1116,7 @@ public class LocationManager {
requestLocationUpdates(
provider,
- new LocationRequest.Builder(minTimeMs)
- .setMinUpdateDistanceMeters(minDistanceM)
- .build(),
+ createFromDeprecatedProvider(provider, minTimeMs, minDistanceM, false),
pendingIntent);
}
@@ -1147,10 +1142,7 @@ public class LocationManager {
Preconditions.checkArgument(criteria != null, "invalid null criteria");
requestLocationUpdates(
FUSED_PROVIDER,
- new LocationRequest.Builder(minTimeMs)
- .setQuality(criteria)
- .setMinUpdateDistanceMeters(minDistanceM)
- .build(),
+ createFromDeprecatedCriteria(criteria, minTimeMs, minDistanceM, false),
pendingIntent);
}
diff --git a/media/Android.bp b/media/Android.bp
index 0ed10472561d..8895b3a9a2ba 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -23,6 +23,25 @@ aidl_interface {
}
aidl_interface {
+ name: "media_permission-aidl",
+ unstable: true,
+ local_include_dir: "java",
+ srcs: [
+ "java/android/media/permission/Identity.aidl",
+ ],
+ backend:
+ {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ // Already generated as part of the entire media java library.
+ enabled: false,
+ },
+ },
+}
+
+aidl_interface {
name: "soundtrigger_middleware-aidl",
unstable: true,
local_include_dir: "java",
@@ -61,5 +80,8 @@ aidl_interface {
enabled: false,
},
},
- imports: [ "audio_common-aidl" ],
+ imports: [
+ "audio_common-aidl",
+ "media_permission-aidl",
+ ],
}
diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java
index d803311fdae3..85b4ba54de63 100644
--- a/media/java/android/media/DrmInitData.java
+++ b/media/java/android/media/DrmInitData.java
@@ -87,13 +87,13 @@ public abstract class DrmInitData {
public final byte[] data;
/**
+ * Creates a new instance with the given values.
+ *
* @param uuid The UUID associated with this scheme initialization data.
* @param mimeType The mimeType of the initialization data.
* @param data The initialization data.
- *
- * @hide
*/
- public SchemeInitData(UUID uuid, String mimeType, byte[] data) {
+ public SchemeInitData(@NonNull UUID uuid, @NonNull String mimeType, @NonNull byte[] data) {
this.uuid = uuid;
this.mimeType = mimeType;
this.data = data;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 57e8e438d592..ddc7db771550 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -17,6 +17,7 @@
package android.media;
import static android.media.ExifInterfaceUtils.byteArrayToHexString;
+import static android.media.ExifInterfaceUtils.closeFileDescriptor;
import static android.media.ExifInterfaceUtils.closeQuietly;
import static android.media.ExifInterfaceUtils.convertToLongArray;
import static android.media.ExifInterfaceUtils.copy;
@@ -1529,9 +1530,8 @@ public class ExifInterface {
mAssetInputStream = null;
mFilename = null;
- // When FileDescriptor is duplicated and set to FileInputStream, ownership needs to be
- // clarified in order for garbage collection to take place.
- boolean isFdOwner = false;
+
+ boolean isFdDuped = false;
if (isSeekableFD(fileDescriptor)) {
mSeekableFileDescriptor = fileDescriptor;
// Keep the original file descriptor in order to save attributes when it's seekable.
@@ -1539,7 +1539,7 @@ public class ExifInterface {
// feature won't be working.
try {
fileDescriptor = Os.dup(fileDescriptor);
- isFdOwner = true;
+ isFdDuped = true;
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
@@ -1549,10 +1549,13 @@ public class ExifInterface {
mIsInputStream = false;
FileInputStream in = null;
try {
- in = new FileInputStream(fileDescriptor, isFdOwner);
+ in = new FileInputStream(fileDescriptor);
loadAttributes(in);
} finally {
closeQuietly(in);
+ if (isFdDuped) {
+ closeFileDescriptor(fileDescriptor);
+ }
}
}
@@ -2199,6 +2202,7 @@ public class ExifInterface {
// Read the thumbnail.
InputStream in = null;
+ FileDescriptor newFileDescriptor = null;
try {
if (mAssetInputStream != null) {
in = mAssetInputStream;
@@ -2211,9 +2215,9 @@ public class ExifInterface {
} else if (mFilename != null) {
in = new FileInputStream(mFilename);
} else if (mSeekableFileDescriptor != null) {
- FileDescriptor fileDescriptor = Os.dup(mSeekableFileDescriptor);
- Os.lseek(fileDescriptor, 0, OsConstants.SEEK_SET);
- in = new FileInputStream(fileDescriptor, true);
+ newFileDescriptor = Os.dup(mSeekableFileDescriptor);
+ Os.lseek(newFileDescriptor, 0, OsConstants.SEEK_SET);
+ in = new FileInputStream(newFileDescriptor);
}
if (in == null) {
// Should not be reached this.
@@ -2234,6 +2238,9 @@ public class ExifInterface {
Log.d(TAG, "Encountered exception while getting thumbnail", e);
} finally {
closeQuietly(in);
+ if (newFileDescriptor != null) {
+ closeFileDescriptor(newFileDescriptor);
+ }
}
return null;
}
diff --git a/media/java/android/media/ExifInterfaceUtils.java b/media/java/android/media/ExifInterfaceUtils.java
index 6ff706e8041f..491fe1d64ab9 100644
--- a/media/java/android/media/ExifInterfaceUtils.java
+++ b/media/java/android/media/ExifInterfaceUtils.java
@@ -16,7 +16,12 @@
package android.media;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Log;
+
import java.io.Closeable;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -25,6 +30,8 @@ import java.io.OutputStream;
* Package private utility class for ExifInterface.
*/
class ExifInterfaceUtils {
+ private static final String TAG = "ExifInterface";
+
/**
* Copies all of the bytes from {@code in} to {@code out}. Neither stream is closed.
* Returns the total number of bytes transferred.
@@ -114,4 +121,15 @@ class ExifInterfaceUtils {
}
}
}
+
+ /**
+ * Closes a file descriptor that has been duplicated.
+ */
+ public static void closeFileDescriptor(FileDescriptor fd) {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException ex) {
+ Log.e(TAG, "Error closing fd.", ex);
+ }
+ }
}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 6ef871383a58..8f603300dc11 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -22,10 +22,6 @@ import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioPresentation;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-import android.media.MediaHTTPService;
import android.net.Uri;
import android.os.IBinder;
import android.os.IHwBinder;
diff --git a/media/java/android/media/permission/ClearCallingIdentityContext.java b/media/java/android/media/permission/ClearCallingIdentityContext.java
new file mode 100644
index 000000000000..364a2e800afe
--- /dev/null
+++ b/media/java/android/media/permission/ClearCallingIdentityContext.java
@@ -0,0 +1,58 @@
+/*
+ * 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 android.media.permission;
+
+import android.annotation.NonNull;
+import android.os.Binder;
+
+/**
+ * An RAII-style object, used to establish a scope in which the binder calling identity is cleared.
+ *
+ * <p>
+ * Intended usage:
+ * <pre>
+ * void caller() {
+ * try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ * // Within this scope the binder calling identity is cleared.
+ * ...
+ * }
+ * // Outside the scope the calling identity is restored to its prior state.
+ * </pre>
+ *
+ * @hide
+ */
+public class ClearCallingIdentityContext implements SafeCloseable {
+ private final long mRestoreKey;
+
+ /**
+ * Creates a new instance.
+ * @return A {@link SafeCloseable}, intended to be used in a try-with-resource block.
+ */
+ public static @NonNull
+ SafeCloseable create() {
+ return new ClearCallingIdentityContext();
+ }
+
+ private ClearCallingIdentityContext() {
+ mRestoreKey = Binder.clearCallingIdentity();
+ }
+
+ @Override
+ public void close() {
+ Binder.restoreCallingIdentity(mRestoreKey);
+ }
+}
diff --git a/media/java/android/media/permission/CompositeSafeCloseable.java b/media/java/android/media/permission/CompositeSafeCloseable.java
new file mode 100644
index 000000000000..08990ebd5057
--- /dev/null
+++ b/media/java/android/media/permission/CompositeSafeCloseable.java
@@ -0,0 +1,40 @@
+/*
+ * 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 android.media.permission;
+
+import android.annotation.NonNull;
+
+/**
+ * A composite {@link SafeCloseable}. Will close its children in reverse order.
+ *
+ * @hide
+ */
+class CompositeSafeCloseable implements SafeCloseable {
+ private final @NonNull SafeCloseable[] mChildren;
+
+ CompositeSafeCloseable(@NonNull SafeCloseable... children) {
+ mChildren = children;
+ }
+
+ @Override
+ public void close() {
+ // Close in reverse order.
+ for (int i = mChildren.length - 1; i >= 0; --i) {
+ mChildren[i].close();
+ }
+ }
+}
diff --git a/media/java/android/media/permission/Identity.aidl b/media/java/android/media/permission/Identity.aidl
new file mode 100644
index 000000000000..361497d59ea9
--- /dev/null
+++ b/media/java/android/media/permission/Identity.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 android.media.permission;
+
+/**
+ * A collection of identity-related information, required for permission enforcement.
+ *
+ * {@hide}
+ */
+parcelable Identity {
+ /** Linux user ID. */
+ int uid;
+ /** Linux process ID. */
+ int pid;
+ /** Package name. If null, the first package owned by the given uid will be assumed. */
+ @nullable String packageName;
+ /** Attribution tag. Mostly used for diagnostic purposes. */
+ @nullable String attributionTag;
+}
diff --git a/media/java/android/media/permission/IdentityContext.java b/media/java/android/media/permission/IdentityContext.java
new file mode 100644
index 000000000000..d10654fbe684
--- /dev/null
+++ b/media/java/android/media/permission/IdentityContext.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.media.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * An RAII-style object, used to establish a scope in which a single identity is part of the
+ * context. This is used in order to avoid having to explicitly pass identity information through
+ * deep call-stacks.
+ * <p>
+ * Intended usage:
+ * <pre>
+ * void caller() {
+ * Identity originator = ...;
+ * try (SafeCloseable ignored = IdentityContext.create(originator)) {
+ * // Within this scope the context is established.
+ * callee();
+ * }
+ * // Outside the scope the context is restored to its prior state.
+ *
+ * void callee() {
+ * // Here we can access the identity without having to explicitly take it as an argument.
+ * // This is true even if this were a deeply nested call.
+ * Identity originator = IdentityContext.getNonNull();
+ * ...
+ * }
+ * </pre>
+ *
+ * @hide
+ */
+public class IdentityContext implements SafeCloseable {
+ private static ThreadLocal<Identity> sThreadLocalIdentity = new ThreadLocal<>();
+ private @Nullable Identity mPrior = get();
+
+ /**
+ * Create a scoped identity context.
+ *
+ * @param identity The identity to establish with the scope.
+ * @return A {@link SafeCloseable}, to be used in a try-with-resources block to establish a
+ * scope.
+ */
+ public static @NonNull
+ SafeCloseable create(@Nullable Identity identity) {
+ return new IdentityContext(identity);
+ }
+
+ /**
+ * Get the current identity context.
+ *
+ * @return The identity, or null if it has not been established.
+ */
+ public static @Nullable
+ Identity get() {
+ return sThreadLocalIdentity.get();
+ }
+
+ /**
+ * Get the current identity context. Throws a {@link NullPointerException} if it has not been
+ * established.
+ *
+ * @return The identity.
+ */
+ public static @NonNull
+ Identity getNonNull() {
+ Identity result = get();
+ if (result == null) {
+ throw new NullPointerException("Identity context is not set");
+ }
+ return result;
+ }
+
+ private IdentityContext(@Nullable Identity identity) {
+ set(identity);
+ }
+
+ @Override
+ public void close() {
+ set(mPrior);
+ }
+
+ private static void set(@Nullable Identity identity) {
+ sThreadLocalIdentity.set(identity);
+ }
+}
diff --git a/media/java/android/media/permission/PermissionUtil.java b/media/java/android/media/permission/PermissionUtil.java
new file mode 100644
index 000000000000..458f11243f68
--- /dev/null
+++ b/media/java/android/media/permission/PermissionUtil.java
@@ -0,0 +1,250 @@
+/*
+ * 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 android.media.permission;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.PermissionChecker;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+
+import java.util.Objects;
+
+/**
+ * This module provides some utility methods for facilitating our permission enforcement patterns.
+ * <p>
+ * <h1>Intended usage:</h1>
+ * Close to the client-facing edge of the server, first authenticate the client, using {@link
+ * #establishIdentityDirect(Identity)}, or {@link #establishIdentityIndirect(Context, String,
+ * Identity, Identity)}, depending on whether the client is trying to authenticate as the
+ * originator or a middleman. Those methods will establish a scope with the originator in the
+ * {@link android.media.permission.IdentityContext} and a cleared binder calling identity.
+ * Typically there would be two distinct API methods for the two different options, and typically
+ * those API methods would be used to establish a client session which is associated with the
+ * originator for the lifetime of the session.
+ * <p>
+ * When performing an operation that requires permissions, use {@link
+ * #checkPermissionForPreflight(Context, Identity, String)} or {@link
+ * #checkPermissionForDataDelivery(Context, Identity, String, String)} on the originator
+ * identity. Note that this won't typically be the identity pulled from the {@link
+ * android.media.permission.IdentityContext}, since we are working with a session-based approach,
+ * the originator identity will be established once upon creation of a session, and then all
+ * interactions with this session will using the identity attached to the session. This also covers
+ * performing checks prior to invoking client callbacks for data delivery.
+ *
+ * @hide
+ */
+public class PermissionUtil {
+ /**
+ * Authenticate an originator, where the binder call is coming from a middleman.
+ *
+ * The middleman is expected to hold a special permission to act as such, or else a
+ * {@link SecurityException} will be thrown. If the call succeeds:
+ * <ul>
+ * <li>The passed middlemanIdentity argument will have its uid/pid fields overridden with
+ * those provided by binder.
+ * <li>An {@link SafeCloseable} is returned, used to established a scope in which the
+ * originator identity is available via {@link android.media.permission.IdentityContext}
+ * and in which the binder
+ * calling ID is cleared.
+ * </ul>
+ * Example usage:
+ * <pre>
+ * try (SafeCloseable ignored = PermissionUtil.establishIdentityIndirect(...)) {
+ * // Within this scope we have the identity context established, and the binder calling
+ * // identity cleared.
+ * ...
+ * Identity originator = IdentityContext.getNonNull();
+ * ...
+ * }
+ * // outside the scope, everything is back to the prior state.
+ * </pre>
+ * <p>
+ * <b>Important note:</b> The binder calling ID will be used to securely establish the identity
+ * of the middleman. However, if the middleman is on the same process as the server,
+ * the middleman must remember to clear the binder calling identity, or else the binder calling
+ * ID will reflect the process calling into the middleman, not the middleman process itself. If
+ * the middleman itself is using this API, this is typically not an issue, since this method
+ * will take care of that.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param middlemanPermission The permission that will be checked in order to authorize the
+ * middleman to act as such (i.e. be trusted to convey the
+ * originator
+ * identity reliably).
+ * @param middlemanIdentity The identity of the middleman.
+ * @param originatorIdentity The identity of the originator.
+ * @return A {@link SafeCloseable}, used to establish a scope, as mentioned above.
+ */
+ public static @NonNull
+ SafeCloseable establishIdentityIndirect(
+ @NonNull Context context,
+ @NonNull String middlemanPermission,
+ @NonNull Identity middlemanIdentity,
+ @NonNull Identity originatorIdentity) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(middlemanPermission);
+ Objects.requireNonNull(middlemanIdentity);
+ Objects.requireNonNull(originatorIdentity);
+
+ // Override uid/pid with the secure values provided by binder.
+ middlemanIdentity.pid = Binder.getCallingPid();
+ middlemanIdentity.uid = Binder.getCallingUid();
+
+ // Authorize middleman to delegate identity.
+ context.enforcePermission(middlemanPermission, middlemanIdentity.pid,
+ middlemanIdentity.uid,
+ String.format("Middleman must have the %s permision.", middlemanPermission));
+ return new CompositeSafeCloseable(IdentityContext.create(originatorIdentity),
+ ClearCallingIdentityContext.create());
+ }
+
+ /**
+ * Authenticate an originator, where the binder call is coming directly from the originator.
+ *
+ * If the call succeeds:
+ * <ul>
+ * <li>The passed originatorIdentity argument will have its uid/pid fields overridden with
+ * those provided by binder.
+ * <li>A {@link SafeCloseable} is returned, used to established a scope in which the
+ * originator identity is available via {@link IdentityContext} and in which the binder
+ * calling ID is cleared.
+ * </ul>
+ * Example usage:
+ * <pre>
+ * try (AutoClosable ignored = PermissionUtil.establishIdentityDirect(...)) {
+ * // Within this scope we have the identity context established, and the binder calling
+ * // identity cleared.
+ * ...
+ * Identity originator = IdentityContext.getNonNull();
+ * ...
+ * }
+ * // outside the scope, everything is back to the prior state.
+ * </pre>
+ * <p>
+ * <b>Important note:</b> The binder calling ID will be used to securely establish the identity
+ * of the client. However, if the client is on the same process as the server, and is itself a
+ * binder server, it must remember to clear the binder calling identity, or else the binder
+ * calling ID will reflect the process calling into the client, not the client process itself.
+ * If the client itself is using this API, this is typically not an issue, since this method
+ * will take care of that.
+ *
+ * @param originatorIdentity The identity of the originator.
+ * @return A {@link SafeCloseable}, used to establish a scope, as mentioned above.
+ */
+ public static @NonNull
+ SafeCloseable establishIdentityDirect(@NonNull Identity originatorIdentity) {
+ Objects.requireNonNull(originatorIdentity);
+
+ originatorIdentity.uid = Binder.getCallingUid();
+ originatorIdentity.pid = Binder.getCallingPid();
+ return new CompositeSafeCloseable(
+ IdentityContext.create(originatorIdentity),
+ ClearCallingIdentityContext.create());
+ }
+
+ /**
+ * Checks whether the given identity has the given permission to receive data.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param identity The identity to check.
+ * @param permission The identifier of the permission we want to check.
+ * @param reason The reason why we're requesting the permission, for auditing purposes.
+ * @return The permission check result which is either
+ * {@link PermissionChecker#PERMISSION_GRANTED}
+ * or {@link PermissionChecker#PERMISSION_SOFT_DENIED} or
+ * {@link PermissionChecker#PERMISSION_HARD_DENIED}.
+ */
+ public static int checkPermissionForDataDelivery(@NonNull Context context,
+ @NonNull Identity identity,
+ @NonNull String permission,
+ @NonNull String reason) {
+ return PermissionChecker.checkPermissionForDataDelivery(context, permission,
+ identity.pid, identity.uid, identity.packageName, identity.attributionTag,
+ reason);
+ }
+
+ /**
+ * Checks whether the given identity has the given permission to receive data.
+ *
+ * This variant ignores the proc-state for the sake of the check, i.e. overrides any
+ * restrictions that apply specifically to apps running in the background.
+ *
+ * TODO(ytai): This is a temporary hack until we have permissions that are specifically intended
+ * for background microphone access.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param identity The identity to check.
+ * @param permission The identifier of the permission we want to check.
+ * @param reason The reason why we're requesting the permission, for auditing purposes.
+ * @return The permission check result which is either
+ * {@link PermissionChecker#PERMISSION_GRANTED}
+ * or {@link PermissionChecker#PERMISSION_SOFT_DENIED} or
+ * {@link PermissionChecker#PERMISSION_HARD_DENIED}.
+ */
+ public static int checkPermissionForDataDeliveryIgnoreProcState(@NonNull Context context,
+ @NonNull Identity identity,
+ @NonNull String permission,
+ @NonNull String reason) {
+ if (context.checkPermission(permission, identity.pid, identity.uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ return PermissionChecker.PERMISSION_HARD_DENIED;
+ }
+
+ String appOpOfPermission = AppOpsManager.permissionToOp(permission);
+ if (appOpOfPermission == null) {
+ // not platform defined
+ return PermissionChecker.PERMISSION_GRANTED;
+ }
+
+ String packageName = identity.packageName;
+ if (packageName == null) {
+ String[] packageNames = context.getPackageManager().getPackagesForUid(identity.uid);
+ if (packageNames != null && packageNames.length > 0) {
+ packageName = packageNames[0];
+ }
+ }
+
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+
+ int appOpMode = appOpsManager.unsafeCheckOpRawNoThrow(appOpOfPermission, identity.uid,
+ packageName);
+ if (appOpMode == AppOpsManager.MODE_ALLOWED) {
+ return PermissionChecker.PERMISSION_GRANTED;
+ }
+ return PermissionChecker.PERMISSION_SOFT_DENIED;
+ }
+
+ /**
+ * Checks whether the given identity has the given permission.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param identity The identity to check.
+ * @param permission The identifier of the permission we want to check.
+ * @return The permission check result which is either
+ * {@link PermissionChecker#PERMISSION_GRANTED}
+ * or {@link PermissionChecker#PERMISSION_SOFT_DENIED} or
+ * {@link PermissionChecker#PERMISSION_HARD_DENIED}.
+ */
+ public static int checkPermissionForPreflight(@NonNull Context context,
+ @NonNull Identity identity,
+ @NonNull String permission) {
+ return PermissionChecker.checkPermissionForPreflight(context, permission,
+ identity.pid, identity.uid, identity.packageName);
+ }
+}
diff --git a/tests/utils/testutils/java/android/view/test/InsetsModeSession.java b/media/java/android/media/permission/SafeCloseable.java
index e05fdce0ca0c..8ec15b18bd37 100644
--- a/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
+++ b/media/java/android/media/permission/SafeCloseable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,24 +14,14 @@
* limitations under the License.
*/
-package android.view.test;
-
-import android.view.ViewRootImpl;
+package android.media.permission;
/**
- * Session to set insets mode for {@link ViewRootImpl#sNewInsetsMode}.
+ * An {@link AutoCloseable} that doesn't throw on {@link #close()}.
+ *
+ * @hide
*/
-public class InsetsModeSession implements AutoCloseable {
-
- private int mOldMode;
-
- public InsetsModeSession(int flag) {
- mOldMode = ViewRootImpl.sNewInsetsMode;
- ViewRootImpl.sNewInsetsMode = flag;
- }
-
+public interface SafeCloseable extends AutoCloseable {
@Override
- public void close() {
- ViewRootImpl.sNewInsetsMode = mOldMode;
- }
+ void close();
}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index 08953392ca18..16a517b72119 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -35,7 +35,7 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Slog;
-import com.android.internal.app.ISoundTriggerService;
+import com.android.internal.app.ISoundTriggerSession;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -64,7 +64,7 @@ public final class SoundTriggerDetector {
private final Object mLock = new Object();
- private final ISoundTriggerService mSoundTriggerService;
+ private final ISoundTriggerSession mSoundTriggerSession;
private final UUID mSoundModelId;
private final Callback mCallback;
private final Handler mHandler;
@@ -266,9 +266,9 @@ public final class SoundTriggerDetector {
* This class should be constructed by the {@link SoundTriggerManager}.
* @hide
*/
- SoundTriggerDetector(ISoundTriggerService soundTriggerService, UUID soundModelId,
+ SoundTriggerDetector(ISoundTriggerSession soundTriggerSession, UUID soundModelId,
@NonNull Callback callback, @Nullable Handler handler) {
- mSoundTriggerService = soundTriggerService;
+ mSoundTriggerSession = soundTriggerSession;
mSoundModelId = soundModelId;
mCallback = callback;
if (handler == null) {
@@ -305,7 +305,7 @@ public final class SoundTriggerDetector {
int status;
try {
- status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerSession.startRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
allowMultipleTriggers, null, null, audioCapabilities));
} catch (RemoteException e) {
@@ -321,7 +321,7 @@ public final class SoundTriggerDetector {
public boolean stopRecognition() {
int status = STATUS_OK;
try {
- status = mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerSession.stopRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback);
} catch (RemoteException e) {
return false;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 7d51b104a47d..0ff8d9e96220 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -33,6 +34,10 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.hardware.soundtrigger.SoundTrigger.SoundModel;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.Identity;
+import android.media.permission.SafeCloseable;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
@@ -41,6 +46,7 @@ import android.provider.Settings;
import android.util.Slog;
import com.android.internal.app.ISoundTriggerService;
+import com.android.internal.app.ISoundTriggerSession;
import com.android.internal.util.Preconditions;
import java.util.HashMap;
@@ -61,7 +67,7 @@ public final class SoundTriggerManager {
private static final String TAG = "SoundTriggerManager";
private final Context mContext;
- private final ISoundTriggerService mSoundTriggerService;
+ private final ISoundTriggerSession mSoundTriggerSession;
// Stores a mapping from the sound model UUID to the SoundTriggerInstance created by
// the createSoundTriggerDetector() call.
@@ -74,7 +80,20 @@ public final class SoundTriggerManager {
if (DBG) {
Slog.i(TAG, "SoundTriggerManager created.");
}
- mSoundTriggerService = soundTriggerService;
+ try {
+ // This assumes that whoever is calling this ctor is the originator of the operations,
+ // as opposed to a service acting on behalf of a separate identity.
+ // Services acting on behalf of some other identity should not be using this class at
+ // all, but rather directly connect to the server and attach with explicit credentials.
+ Identity originatorIdentity = new Identity();
+ originatorIdentity.packageName = ActivityThread.currentOpPackageName();
+
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mSoundTriggerSession = soundTriggerService.attachAsOriginator(originatorIdentity);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
mContext = context;
mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
}
@@ -85,7 +104,7 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public void updateModel(Model model) {
try {
- mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
+ mSoundTriggerSession.updateSoundModel(model.getGenericSoundModel());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -102,7 +121,7 @@ public final class SoundTriggerManager {
public Model getModel(UUID soundModelId) {
try {
GenericSoundModel model =
- mSoundTriggerService.getSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId));
if (model == null) {
return null;
}
@@ -119,7 +138,7 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public void deleteModel(UUID soundModelId) {
try {
- mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.deleteSoundModel(new ParcelUuid(soundModelId));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -149,7 +168,7 @@ public final class SoundTriggerManager {
if (oldInstance != null) {
// Shutdown old instance.
}
- SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerService,
+ SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerSession,
soundModelId, callback, handler);
mReceiverInstanceMap.put(soundModelId, newInstance);
return newInstance;
@@ -309,10 +328,10 @@ public final class SoundTriggerManager {
try {
switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- return mSoundTriggerService.loadGenericSoundModel(
+ return mSoundTriggerSession.loadGenericSoundModel(
(GenericSoundModel) soundModel);
case SoundModel.TYPE_KEYPHRASE:
- return mSoundTriggerService.loadKeyphraseSoundModel(
+ return mSoundTriggerSession.loadKeyphraseSoundModel(
(KeyphraseSoundModel) soundModel);
default:
Slog.e(TAG, "Unkown model type");
@@ -351,7 +370,7 @@ public final class SoundTriggerManager {
Preconditions.checkNotNull(config);
try {
- return mSoundTriggerService.startRecognitionForService(new ParcelUuid(soundModelId),
+ return mSoundTriggerSession.startRecognitionForService(new ParcelUuid(soundModelId),
params, detectionService, config);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -369,7 +388,7 @@ public final class SoundTriggerManager {
return STATUS_ERROR;
}
try {
- return mSoundTriggerService.stopRecognitionForService(new ParcelUuid(soundModelId));
+ return mSoundTriggerSession.stopRecognitionForService(new ParcelUuid(soundModelId));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -386,7 +405,7 @@ public final class SoundTriggerManager {
return STATUS_ERROR;
}
try {
- return mSoundTriggerService.unloadSoundModel(
+ return mSoundTriggerSession.unloadSoundModel(
new ParcelUuid(soundModelId));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -404,7 +423,7 @@ public final class SoundTriggerManager {
return false;
}
try {
- return mSoundTriggerService.isRecognitionActive(
+ return mSoundTriggerSession.isRecognitionActive(
new ParcelUuid(soundModelId));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -439,7 +458,7 @@ public final class SoundTriggerManager {
return STATUS_ERROR;
}
try {
- return mSoundTriggerService.getModelState(new ParcelUuid(soundModelId));
+ return mSoundTriggerSession.getModelState(new ParcelUuid(soundModelId));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -455,7 +474,7 @@ public final class SoundTriggerManager {
public SoundTrigger.ModuleProperties getModuleProperties() {
try {
- return mSoundTriggerService.getModuleProperties();
+ return mSoundTriggerSession.getModuleProperties();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -481,7 +500,7 @@ public final class SoundTriggerManager {
public int setParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam, int value) {
try {
- return mSoundTriggerService.setParameter(new ParcelUuid(soundModelId), modelParam,
+ return mSoundTriggerSession.setParameter(new ParcelUuid(soundModelId), modelParam,
value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -504,7 +523,7 @@ public final class SoundTriggerManager {
public int getParameter(@NonNull UUID soundModelId,
@ModelParams int modelParam) {
try {
- return mSoundTriggerService.getParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.getParameter(new ParcelUuid(soundModelId), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -524,7 +543,7 @@ public final class SoundTriggerManager {
public ModelParamRange queryParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam) {
try {
- return mSoundTriggerService.queryParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.queryParameter(new ParcelUuid(soundModelId), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl b/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
index 06c39071cdf5..d1126b9006e0 100644
--- a/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
+++ b/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
@@ -15,6 +15,7 @@
*/
package android.media.soundtrigger_middleware;
+import android.media.permission.Identity;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
@@ -30,13 +31,59 @@ import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
interface ISoundTriggerMiddlewareService {
/**
* Query the available modules and their capabilities.
+ *
+ * This variant is intended for use by the originator of the operations for permission
+ * enforcement purposes. The provided identity's uid/pid fields will be ignored and overridden
+ * by the ones provided by Binder.getCallingUid() / Binder.getCallingPid().
*/
- SoundTriggerModuleDescriptor[] listModules();
+ SoundTriggerModuleDescriptor[] listModulesAsOriginator(in Identity identity);
+
+ /**
+ * Query the available modules and their capabilities.
+ *
+ * This variant is intended for use by a trusted "middleman", acting on behalf of some identity
+ * other than itself. The caller must provide:
+ * - Its own identity, which will be used to establish trust via the
+ * SOUNDTRIGGER_DELEGATE_IDENTITY permission. This identity's uid/pid fields will be ignored
+ * and overridden by the ones provided by Binder.getCallingUid() / Binder.getCallingPid().
+ * This implies that the caller must clear its caller identity to protect from the case where
+ * it resides in the same process as the callee.
+ * - The identity of the entity on behalf of which module operations are to be performed.
+ */
+ SoundTriggerModuleDescriptor[] listModulesAsMiddleman(in Identity middlemanIdentity,
+ in Identity originatorIdentity);
+
+ /**
+ * Attach to one of the available modules.
+ *
+ * This variant is intended for use by the originator of the operations for permission
+ * enforcement purposes. The provided identity's uid/pid fields will be ignored and overridden
+ * by the ones provided by Binder.getCallingUid() / Binder.getCallingPid().
+ *
+ * listModules() must be called prior to calling this method and the provided handle must be
+ * one of the handles from the returned list.
+ */
+ ISoundTriggerModule attachAsOriginator(int handle,
+ in Identity identity,
+ ISoundTriggerCallback callback);
/**
* Attach to one of the available modules.
+ *
+ * This variant is intended for use by a trusted "middleman", acting on behalf of some identity
+ * other than itself. The caller must provide:
+ * - Its own identity, which will be used to establish trust via the
+ * SOUNDTRIGGER_DELEGATE_IDENTITY permission. This identity's uid/pid fields will be ignored
+ * and overridden by the ones provided by Binder.getCallingUid() / Binder.getCallingPid().
+ * This implies that the caller must clear its caller identity to protect from the case where
+ * it resides in the same process as the callee.
+ * - The identity of the entity on behalf of which module operations are to be performed.
+ *
* listModules() must be called prior to calling this method and the provided handle must be
* one of the handles from the returned list.
*/
- ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback);
-} \ No newline at end of file
+ ISoundTriggerModule attachAsMiddleman(int handle,
+ in Identity middlemanIdentity,
+ in Identity originatorIdentity,
+ ISoundTriggerCallback callback);
+}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 1186c704526a..80300611c7f2 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -11359,6 +11359,7 @@ package android.content.pm {
field public static final int CONFIG_COLOR_MODE = 16384; // 0x4000
field public static final int CONFIG_DENSITY = 4096; // 0x1000
field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
+ field public static final int CONFIG_FORCE_BOLD_TEXT = 268435456; // 0x10000000
field public static final int CONFIG_KEYBOARD = 16; // 0x10
field public static final int CONFIG_KEYBOARD_HIDDEN = 32; // 0x20
field public static final int CONFIG_LAYOUT_DIRECTION = 8192; // 0x2000
@@ -11451,6 +11452,7 @@ package android.content.pm {
method public int describeContents();
method public int getKind();
method @Nullable public java.security.cert.Certificate getSourceCertificate() throws java.security.cert.CertificateException;
+ method @Nullable public String getSourcePackageName();
method @Nullable public String getSplitName();
method @NonNull public byte[] getValue();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -11559,6 +11561,7 @@ package android.content.pm {
}
public final class Checksum implements android.os.Parcelable {
+ ctor public Checksum(int, @NonNull byte[]);
method public int describeContents();
method public int getKind();
method @NonNull public byte[] getValue();
@@ -11566,9 +11569,9 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Checksum> CREATOR;
field public static final int PARTIAL_MERKLE_ROOT_1M_SHA256 = 32; // 0x20
field public static final int PARTIAL_MERKLE_ROOT_1M_SHA512 = 64; // 0x40
- field public static final int WHOLE_MD5 = 2; // 0x2
+ field @Deprecated public static final int WHOLE_MD5 = 2; // 0x2
field public static final int WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
- field public static final int WHOLE_SHA1 = 4; // 0x4
+ field @Deprecated public static final int WHOLE_SHA1 = 4; // 0x4
field public static final int WHOLE_SHA256 = 8; // 0x8
field public static final int WHOLE_SHA512 = 16; // 0x10
}
@@ -11864,7 +11867,7 @@ package android.content.pm {
public static class PackageInstaller.Session implements java.io.Closeable {
method public void abandon();
- method public void addChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>) throws java.io.IOException;
+ method @Deprecated public void addChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>) throws java.io.IOException;
method public void addChildSessionId(int);
method public void close();
method public void commit(@NonNull android.content.IntentSender);
@@ -12680,6 +12683,9 @@ package android.content.res {
field public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
+ field public static final int FORCE_BOLD_TEXT_NO = 1; // 0x1
+ field public static final int FORCE_BOLD_TEXT_UNDEFINED = 0; // 0x0
+ field public static final int FORCE_BOLD_TEXT_YES = 2; // 0x2
field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
field public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
field public static final int HARDKEYBOARDHIDDEN_YES = 2; // 0x2
@@ -12746,6 +12752,7 @@ package android.content.res {
field public int colorMode;
field public int densityDpi;
field public float fontScale;
+ field public int forceBoldText;
field public int hardKeyboardHidden;
field public int keyboard;
field public int keyboardHidden;
@@ -24869,6 +24876,7 @@ package android.media {
}
public static final class DrmInitData.SchemeInitData {
+ ctor public DrmInitData.SchemeInitData(@NonNull java.util.UUID, @NonNull String, @NonNull byte[]);
field @NonNull public static final java.util.UUID UUID_NIL;
field public final byte[] data;
field public final String mimeType;
@@ -42429,54 +42437,8 @@ package android.service.textservice {
package android.service.voice {
- public class AlwaysOnHotwordDetector {
- method public android.content.Intent createEnrollIntent();
- method public android.content.Intent createReEnrollIntent();
- method public android.content.Intent createUnEnrollIntent();
- method public int getParameter(int);
- method public int getSupportedAudioCapabilities();
- method public int getSupportedRecognitionModes();
- method @Nullable public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
- method public int setParameter(int, int);
- method public boolean startRecognition(int);
- method public boolean stopRecognition();
- field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
- field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
- field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
- field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
- field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
- field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
- field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
- field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
- field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
- field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
- field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
- field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
- field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
- }
-
- public abstract static class AlwaysOnHotwordDetector.Callback {
- ctor public AlwaysOnHotwordDetector.Callback();
- method public abstract void onAvailabilityChanged(int);
- method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
- method public abstract void onError();
- method public abstract void onRecognitionPaused();
- method public abstract void onRecognitionResumed();
- }
-
- public static class AlwaysOnHotwordDetector.EventPayload {
- method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
- method @Nullable public byte[] getTriggerAudio();
- }
-
- public static final class AlwaysOnHotwordDetector.ModelParamRange {
- method public int getEnd();
- method public int getStart();
- }
-
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
- method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method public int getDisabledShowContext();
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index ae576d4e01ad..3810325c982f 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -108,6 +108,7 @@ package android.os {
package android.provider {
public final class DeviceConfig {
+ field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
}
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 82f2021af425..10fe058bb76f 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -9135,7 +9135,53 @@ package android.service.trust {
package android.service.voice {
+ public class AlwaysOnHotwordDetector {
+ method @Nullable public android.content.Intent createEnrollIntent();
+ method @Nullable public android.content.Intent createReEnrollIntent();
+ method @Nullable public android.content.Intent createUnEnrollIntent();
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int getParameter(int);
+ method public int getSupportedAudioCapabilities();
+ method public int getSupportedRecognitionModes();
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public android.service.voice.AlwaysOnHotwordDetector.ModelParamRange queryParameter(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public int setParameter(int, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition(int);
+ method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean stopRecognition();
+ field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
+ field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
+ field public static final int MODEL_PARAM_THRESHOLD_FACTOR = 0; // 0x0
+ field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
+ field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
+ field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
+ field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
+ field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
+ field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
+ field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
+ field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
+ field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
+ field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
+ }
+
+ public abstract static class AlwaysOnHotwordDetector.Callback {
+ ctor public AlwaysOnHotwordDetector.Callback();
+ method public abstract void onAvailabilityChanged(int);
+ method public abstract void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
+ method public abstract void onError();
+ method public abstract void onRecognitionPaused();
+ method public abstract void onRecognitionResumed();
+ }
+
+ public static class AlwaysOnHotwordDetector.EventPayload {
+ method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
+ method @Nullable public byte[] getTriggerAudio();
+ }
+
+ public static final class AlwaysOnHotwordDetector.ModelParamRange {
+ method public int getEnd();
+ method public int getStart();
+ }
+
public class VoiceInteractionService extends android.app.Service {
+ method @NonNull public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
}
@@ -9526,6 +9572,26 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
+ public final class CallForwardingInfo implements android.os.Parcelable {
+ ctor public CallForwardingInfo(boolean, int, @Nullable String, int);
+ method public int describeContents();
+ method @Nullable public String getNumber();
+ method public int getReason();
+ method public int getTimeoutSeconds();
+ method public boolean isEnabled();
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
+ field public static final int ERROR_FDN_CHECK_FAILURE = 2; // 0x2
+ field public static final int ERROR_NOT_SUPPORTED = 3; // 0x3
+ field public static final int ERROR_UNKNOWN = 1; // 0x1
+ field public static final int REASON_ALL = 4; // 0x4
+ field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int REASON_BUSY = 1; // 0x1
+ field public static final int REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int REASON_NO_REPLY = 2; // 0x2
+ field public static final int REASON_UNCONDITIONAL = 0; // 0x0
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -10187,6 +10253,8 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -10263,6 +10331,8 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingStatus(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -10300,6 +10370,10 @@ package android.telephony {
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
+ field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
+ field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
+ field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -10354,6 +10428,11 @@ package android.telephony {
field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
}
+ public static interface TelephonyManager.CallForwardingInfoCallback {
+ method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo);
+ method public void onError(int);
+ }
+
public final class UiccAccessRule implements android.os.Parcelable {
ctor public UiccAccessRule(byte[], @Nullable String, long);
method public int describeContents();
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 3af7507ae2b4..c190ae54b1cf 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -124,7 +124,7 @@ public class CarKeyguardViewController extends OverlayViewController implements
}
@Override
- protected boolean shouldShowNavigationBar() {
+ protected boolean shouldShowNavigationBarInsets() {
return true;
}
@@ -157,7 +157,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();
}
@@ -172,7 +171,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();
@@ -217,7 +215,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/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index 8d91e7eae91a..c7155f4b21d2 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -193,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;
}
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 66bfb2d316ae..3a7fac9c0e79 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 d928ad0f42c9..44cb5cf9cb54 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
@@ -238,7 +238,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
}
onAnimateCollapsePanel();
- getOverlayViewGlobalStateController().setWindowFocusable(false);
animatePanel(mClosingVelocity, /* isClosing= */ true);
}
@@ -415,7 +414,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
getOverlayViewGlobalStateController().hideView(/* panelViewController= */ this);
}
getLayout().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- getOverlayViewGlobalStateController().setWindowFocusable(visible);
}
/* ***************************************************************************************** *
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 22b6455dbe2b..c13e486f1c0e 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;
@@ -119,6 +118,7 @@ public class OverlayViewGlobalStateController {
updateInternalsWhenShowingView(viewController);
refreshInsetTypesToFit();
+ refreshWindowFocus();
refreshNavigationBarVisibility();
refreshStatusBarVisibility();
@@ -191,6 +191,7 @@ public class OverlayViewGlobalStateController {
mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
refreshHighestZOrderWhenHidingView(viewController);
refreshInsetTypesToFit();
+ refreshWindowFocus();
refreshNavigationBarVisibility();
refreshStatusBarVisibility();
@@ -215,23 +216,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 81b1bf930e7e..887329359b05 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 c7354ed5b459..b113d29f00e6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
@@ -36,6 +36,8 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.TransactionPool;
+import java.util.Objects;
+
/**
* Controller that maps between displays and {@link IDisplayWindowInsetsController} in order to
* give system bar control to SystemUI.
@@ -47,6 +49,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
private static final String TAG = "DisplaySystemBarsController";
private final Context mContext;
+ private final DisplayController mDisplayController;
private SparseArray<PerDisplay> mPerDisplaySparseArray;
public DisplaySystemBarsController(
@@ -57,6 +60,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
TransactionPool transactionPool) {
super(wmService, displayController, mainHandler, transactionPool);
mContext = context;
+ mDisplayController = displayController;
}
@Override
@@ -92,7 +96,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
}
@VisibleForTesting
- class PerDisplay extends IDisplayWindowInsetsController.Stub {
+ class PerDisplay extends DisplayImeController.PerDisplay {
int mDisplayId;
InsetsController mInsetsController;
@@ -100,6 +104,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
String mPackageName;
PerDisplay(int displayId) {
+ super(displayId, mDisplayController.getDisplayLayout(displayId).rotation());
mDisplayId = displayId;
mInsetsController = new InsetsController(
new DisplaySystemBarsInsetsControllerHost(mHandler, this));
@@ -107,6 +112,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
@Override
public void insetsChanged(InsetsState insetsState) {
+ super.insetsChanged(insetsState);
if (mInsetsState.equals(insetsState)) {
return;
}
@@ -120,24 +126,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/window/OverlayPanelViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
index bed803eedc22..f5f3ea3030da 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/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index eb89ee56345a..4bc7bf6e5d1f 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Switserse Duits"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgies"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgaars"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiaans"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Deens"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noors"</string>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index 2970bfe722d8..7a4ffeff433a 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"የስዊዝ ጀርመን"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ቤልጂየም"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ቡልጋሪያ"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ጣሊያንኛ"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ዴኒሽ"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ኖርዌጂያ"</string>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 12751dbceb5b..3b00576afd89 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"الألمانية السويسرية"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"البلجيكية"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"البلغارية"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"الإيطالية"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"الدانماركية"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"النرويجية"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"الفنلندية"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"الكرواتية"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"التشيكية"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"‏لوحة المفاتيح التشيكية بنمط QWERTY"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"الإستونية"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"المجرية"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"الأيسلندية"</string>
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
index a2df66cb1995..a63821e76633 100644
--- a/packages/InputDevices/res/values-as/strings.xml
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ছুইছ জাৰ্মান"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"বেলজিয়ান"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"বুলগেৰিয়ান"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ইটালিয়ান"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ডেনিশ্ব"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ন\'ৰৱেয়ান"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ফিনিশ্ব"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"ক্ৰ\'ৱেশ্বিয়ান"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"চ্চেক"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Czech QWERTY কীব’ৰ্ড"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"ইষ্ট\'নিয়া"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"হাংগেৰিয়ান"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"আইচলেণ্ডিক"</string>
diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml
index 1d9eb0687c7d..16badc456e73 100644
--- a/packages/InputDevices/res/values-az/strings.xml
+++ b/packages/InputDevices/res/values-az/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"İsveçrə Almanı"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belçikalı"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bolqar"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"İtalyan"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danimarkalı"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norveçli"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Fin"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Xorvat"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Çex"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Çex QWERTY üslubu"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Eston"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Macar"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"İslandiyalı"</string>
diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
index 7952c22caa67..95ef45916031 100644
--- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml
+++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švajcarsko nemačka"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgijska"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bugarska"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italijanska"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"danska"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norveška"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"finska"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"hrvatska"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"češka"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Stil češke QWERTY tastature"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"estonska"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"mađarska"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"islandska"</string>
diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml
index 4e2d5ba9216f..63b899af1c98 100644
--- a/packages/InputDevices/res/values-be/strings.xml
+++ b/packages/InputDevices/res/values-be/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Нямецкая (Швейцарыя)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Бельгійская"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Балгарская"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Італьянская"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дацкая"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Нарвежская"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Фінская"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Харвацкая"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Чэшская"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Чэшская раскладка клавіятуры QWERTY"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Эстонская"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Венгерская"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Ісландская"</string>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index a1edb21d4b5a..90b7f6c5e9d3 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"швейцарски немски"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"белгийски"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"български"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"италиански"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"датски"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"норвежки"</string>
diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml
index d3b47bc3c76b..19292780875e 100644
--- a/packages/InputDevices/res/values-bn/strings.xml
+++ b/packages/InputDevices/res/values-bn/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"সুইস জার্মান"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"বেলজিয়ান"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"বুলগেরীয়"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ইতালীয়"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ডেনিশ"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"নরওয়েজীয়"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ফিনিশ"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"ক্রোয়েশিয়"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"চেক"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"চেক QWERTY স্টাইল"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"এস্তোনীয়"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"হাঙ্গেরিয়"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"আইসল্যান্ডিক"</string>
diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml
index 436a3b02eb54..f6a229c34eb4 100644
--- a/packages/InputDevices/res/values-bs/strings.xml
+++ b/packages/InputDevices/res/values-bs/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švicarski njemački"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgijski"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bugarski"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italijanski"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"danski"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norveški"</string>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 1f089e18d5cb..ec3b247ac6d3 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemany suís"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgar"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italià"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danès"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noruec"</string>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index b36861a99cc0..99aed5e6ea0e 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švýcarské (němčina)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgické"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bulharské"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italské"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"dánské"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norské"</string>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index 7e446fd44bc4..dbe685cb2329 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Schweizertysk"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgisk"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarsk"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiensk"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dansk"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norsk"</string>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index c8a7ab1f34fe..fd7fca014548 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Schweizerdeutsch"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgisch"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarisch"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italienisch"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dänisch"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegisch"</string>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index ff7cd022cee7..8bdd6f8bc967 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Γερμανικά Ελβετίας"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Βελγικά"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Βουλγαρικά"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Ιταλικά"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Δανικά"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Νορβηγικά"</string>
diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml
index 02a8e6d4138f..f79c3daf25ef 100644
--- a/packages/InputDevices/res/values-en-rAU/strings.xml
+++ b/packages/InputDevices/res/values-en-rAU/strings.xml
@@ -19,6 +19,7 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarian"</string>
+ <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"Bulgarian, phonetic"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegian"</string>
diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml
index 02a8e6d4138f..f79c3daf25ef 100644
--- a/packages/InputDevices/res/values-en-rCA/strings.xml
+++ b/packages/InputDevices/res/values-en-rCA/strings.xml
@@ -19,6 +19,7 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarian"</string>
+ <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"Bulgarian, phonetic"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegian"</string>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 02a8e6d4138f..f79c3daf25ef 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -19,6 +19,7 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarian"</string>
+ <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"Bulgarian, phonetic"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegian"</string>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 02a8e6d4138f..f79c3daf25ef 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -19,6 +19,7 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarian"</string>
+ <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"Bulgarian, phonetic"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegian"</string>
diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml
index a8d342f04258..d0881864efef 100644
--- a/packages/InputDevices/res/values-en-rXC/strings.xml
+++ b/packages/InputDevices/res/values-en-rXC/strings.xml
@@ -19,6 +19,7 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎Swiss German‎‏‎‎‏‎"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎Belgian‎‏‎‎‏‎"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎Bulgarian‎‏‎‎‏‎"</string>
+ <string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎Bulgarian, Phonetic‎‏‎‎‏‎"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎Italian‎‏‎‎‏‎"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎Danish‎‏‎‎‏‎"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎Norwegian‎‏‎‎‏‎"</string>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 9090cb7b02b2..5319f968afc3 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemán de Suiza"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danés"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noruego"</string>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 66ea65557538..95b3b1c80cdf 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemán suizo"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danés"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noruego"</string>
diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml
index 9674a0d1d616..a5fb8ac08502 100644
--- a/packages/InputDevices/res/values-et/strings.xml
+++ b/packages/InputDevices/res/values-et/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Šveitsisaksa"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgia"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgaaria"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Itaalia"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Taani"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norra"</string>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 357b6184648f..1c75a7c0f67f 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemana (Suitza)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgikarra"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgariarra"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiarra"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Daniarra"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvegiarra"</string>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index 5395d27c2cef..ca7d43a1400f 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"آلمانی سوئیسی"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"بلژیکی"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"بلغاری"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ایتالیایی"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"دانمارکی"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"نروژی"</string>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index d4b0580dac69..2878c78318f7 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"sveitsinsaksa"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgialainen"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bulgaria"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italia"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"tanska"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norja"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"suomi"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"kroaatti"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"tšekki"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"tšekki (QWERTY-tyyli)"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"viro"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"unkari"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"islanti"</string>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index e714e8380800..697fff6f1339 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Allemand (Suisse)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belge"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgare"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italien"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danois"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvégien"</string>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 0a022f192ea2..2e14019340fc 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Allemand (Suisse)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belge"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgare"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italien"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danois"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvégien"</string>
diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml
index 0c86f816fa85..e1ca7cfefa1c 100644
--- a/packages/InputDevices/res/values-gl/strings.xml
+++ b/packages/InputDevices/res/values-gl/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemán suízo"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dinamarqués"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noruegués"</string>
diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml
index 8648389db862..bc2ee8303290 100644
--- a/packages/InputDevices/res/values-gu/strings.xml
+++ b/packages/InputDevices/res/values-gu/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"સ્વિસ જર્મન"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"બેલ્જિયન"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"બલ્ગેરિયન"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ઇટાલિયન"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ડેનિશ"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"નોર્વેજીયન"</string>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 6e674edbedc1..2ffebdd2c1ff 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"स्विस जर्मन"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"बेल्जियाई"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"बुल्‍गारियाई"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"इटैलियन"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"डैनिश"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"नार्वेजियाई"</string>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index cd2dcc183058..0430f8662014 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švicarsko-njemačka"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgijska"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bugarska"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"talijanska"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"danska"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norveška"</string>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 1c7a89a06059..76d10f544280 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"svájci német"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bolgár"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"olasz"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"dán"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norvég"</string>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index fff9fbc5bfd8..fa4e24550639 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Շվեյցարական գերմաներեն"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Բելգիական"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Բուլղարերեն"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Իտալերեն"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Դանիերեն"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Նորվեգերեն"</string>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 04a6dfa38bdd..f5d173a338a0 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Jerman Swiss"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgia"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgaria"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italia"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Denmark"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegia"</string>
diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml
index a60332a3f979..09eedd300177 100644
--- a/packages/InputDevices/res/values-is/strings.xml
+++ b/packages/InputDevices/res/values-is/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Svissneskt-þýskt"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgískt"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgarskt"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Ítalskt"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danskt"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norskt"</string>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index ac137e41b945..e15c01ff6a62 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Tedesco svizzero"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danese"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvegese"</string>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index 544dde22c2cb..4abdf87ec4d4 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"גרמנית שוויצרית"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"בלגית"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"בולגרית"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"איטלקית"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"דנית"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"נורווגית"</string>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 717cbb985c74..606ab3cd2239 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ドイツ語(スイス)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ベルギー語"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ブルガリア語"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"イタリア語"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"デンマーク語"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ノルウェー語"</string>
diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml
index ee42b35440b3..b4b1a2df4d30 100644
--- a/packages/InputDevices/res/values-ka/strings.xml
+++ b/packages/InputDevices/res/values-ka/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"შვეიცარიული გერმანული"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ბელგიური"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ბულგარული"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"იტალიური"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"დანიური"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ნორვეგიული"</string>
diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml
index e4ad73e2efd4..cfdc3f85de4a 100644
--- a/packages/InputDevices/res/values-kk/strings.xml
+++ b/packages/InputDevices/res/values-kk/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Швейцариялық неміс"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Бельгиялық"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Болгар"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Италиян"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дат"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвег"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Фин"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Хорват"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Чех"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Чех (QWERTY)"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Эстон"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Мадияр"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Исланд"</string>
diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml
index a2c3262559c9..2aaf816c7deb 100644
--- a/packages/InputDevices/res/values-km/strings.xml
+++ b/packages/InputDevices/res/values-km/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"អាល្លឺម៉ង់ ស្វីស"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"បែលហ្ស៊ិក"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ប៊ុលហ្ការី"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"អ៊ីតាលី"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ដាណឺម៉ាក"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ន័រវែស"</string>
diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml
index 846101c57c4a..8f62eb36a1f6 100644
--- a/packages/InputDevices/res/values-kn/strings.xml
+++ b/packages/InputDevices/res/values-kn/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ಸ್ವಿಸ್ ಜರ್ಮನ್"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ಬೆಲ್ಜಿಯನ್"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ಬಲ್ಗೇರಿಯನ್‌"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ಇಟಾಲಿಯನ್"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ಡ್ಯಾನಿಶ್"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ನಾರ್ವೇಜಿಯನ್"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ಫಿನ್ನಿಷ್"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"ಕ್ರೊಯೇಶಿಯನ್"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"ಜೆಕ್"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ಝೆಕ್ QWERTY ಶೈಲಿ"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"ಎಸ್ಟೋನಿಯನ್"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ಹಂಗೇರಿಯನ್"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ಐಸ್‌ಲ್ಯಾಂಡಿಕ್"</string>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 2677432970da..b1f658202c46 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"독일어(스위스)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"벨기에어"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"불가리아어"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"이탈리아어"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"덴마크어"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"노르웨이어"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"핀란드어"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"크로아티아어"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"체코어"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"체코어 QWERTY 키보드"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"에스토니아어"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"헝가리어"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"아이슬란드어"</string>
diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml
index 15a504ea4f59..bc521a2cd6cb 100644
--- a/packages/InputDevices/res/values-ky/strings.xml
+++ b/packages/InputDevices/res/values-ky/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Немис (Швейцария)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Белгия"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Болгар"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Италия"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дания"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвег"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Фин"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Хорват"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Чех"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Чехиялык QWERTY стили"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Эстон"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Венгр"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Исландия"</string>
diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml
index 26e7ad471bad..edb59f3964ed 100644
--- a/packages/InputDevices/res/values-lo/strings.xml
+++ b/packages/InputDevices/res/values-lo/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ສະວິສ ເຢຍລະມັນ"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ເບວຢ້ຽນ"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ຮັງກາຣຽນ"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ອິຕາລຽນ"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ເດັນນິຊ"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ນໍເວກຽນ"</string>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index d0b855d10822..f33eb42e6a4f 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Šveicarijos vokiečių k."</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgų k."</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarų k."</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italų k."</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danų k."</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvegų k."</string>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index f3758390380d..4f47a3ba65db 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Vācu (Šveice)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Beļģu"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgāru"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Itāļu"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dāņu"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvēģu"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Somu"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Horvātu"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Čehu"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Čehu (QWERTY)"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Igauņu"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Ungāru"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Īslandiešu"</string>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index ce5e8f22f8ef..c036409c9c62 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Германски (Швајцарија)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Белгиски"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Бугарски"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Италијански"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дански"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвешки"</string>
diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml
index cb65e9c40822..65fbf22d5fe7 100644
--- a/packages/InputDevices/res/values-ml/strings.xml
+++ b/packages/InputDevices/res/values-ml/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"സ്വിസ് ജര്‍മന്‍"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ബെൽജിയൻ"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ബൾഗേറിയൻ"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ഇറ്റാലിയൻ"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ഡാനിഷ്"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"നോർവീജിയൻ"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ഫിന്നിഷ്"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"ക്രൊയേഷ്യൻ"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"ചെക്ക്"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ചെക്ക് QWERTY ശെെലി"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"എസ്റ്റോണിയൻ"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ഹംഗേറിയൻ"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ഐസ്‌ലാന്‍ഡിക്"</string>
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index f405750e941d..a8fc6615f4c1 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Швейцарийн Герман"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Бельги"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Болгар"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Итали"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дани"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвеги"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Финлянд"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Хорват"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Чех"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Чех хэлний QWERTY загвар"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Эстон"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Унгар"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Исланд"</string>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index ba31233e0006..da6caab3842e 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"स्विस जर्मन"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"बेल्जियन"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"बल्गेरियन"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"इटालियन"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"डॅनिश"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"नॉर्वेजियन"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"फिन्निश"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"क्रोएशियन"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"झेक"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Czech QWERTY शैली"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"एस्टोनियन"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"हंगेरियन"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"आइसलँडिक"</string>
diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml
index 09afb200773f..975024ba1cdf 100644
--- a/packages/InputDevices/res/values-ms/strings.xml
+++ b/packages/InputDevices/res/values-ms/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Jerman Switzerland"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Bahasa Belgium"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bahasa Bulgaria"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Bahasa Itali"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Bahasa Denmark"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Bahasa Norway"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Bahasa Finland"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Bahasa Croatia"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Bahasa Czech"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Gaya QWERTY Czech"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Bahasa Estonia"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Bahasa Hungary"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Bahasa Iceland"</string>
diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml
index 57748dbfa4e1..5484d9d2a2e8 100644
--- a/packages/InputDevices/res/values-my/strings.xml
+++ b/packages/InputDevices/res/values-my/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ဆွစ် ဂျာမန်"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ဘယ်လ်ဂျီယန်"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ဘူဂေးရီယန်း"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"အီတာလီယန်"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ဒိန်းမတ်"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"နောဝေဂျီယန်"</string>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 6059b4c8a822..54840338b966 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Sveitsisk standardtysk"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgisk"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarsk"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiensk"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dansk"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norsk"</string>
diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml
index 731c88fe4077..24816c1126e3 100644
--- a/packages/InputDevices/res/values-ne/strings.xml
+++ b/packages/InputDevices/res/values-ne/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"स्विस-जर्मन"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"बेल्जियन"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"बुल्गेरियन"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"इटालियन"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"डेनिश"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"नर्वेजियन"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"फिनिश"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"क्रोशीयाली"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"चेक"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"चेक भाषामा QWERTY शैली"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"एस्तोनीयाली"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"हंगेरियन"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"आइसल्याण्डिक"</string>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index 9767f92d72e4..e000a30f9cf9 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Zwitsers Duits"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgisch"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgaars"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiaans"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Deens"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Noors"</string>
@@ -26,7 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Fins"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Kroatisch"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Tsjechisch"</string>
- <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Tsjechisch - QWERTY-stijl"</string>
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Tsjechisch - QWERTY-toetsenbord"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Estlands"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Hongaars"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"IJslands"</string>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
index 04d44dcac860..6185ff77695d 100644
--- a/packages/InputDevices/res/values-or/strings.xml
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ସୁଇସ୍ ଜର୍ମାନ୍‍"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ବେଲ୍‍ଜିଆନ୍‍"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ବୁଲଗାରିଆନ୍‍"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ଇଟାଲିୟାନ୍‌"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ଡାନିଶ୍‍"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ନରୱେଜିଆନ୍"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ଫିନ୍ନିଶ୍‍"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"କ୍ରୋଆଶିଆନ୍"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"ଚେକ୍"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ଚେକ୍ QWERTY ଷ୍ଟାଇଲ୍"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"ଇଷ୍ଟୋନିଆନ୍"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ହଙ୍ଗେରିଆନ୍"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ଆଇସଲାଣ୍ଡିକ୍"</string>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 2eb30c90dd42..97cf28bbc66c 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ਸਵਿਸ ਜਰਮਨ"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"ਬੈਲਜੀਅਨ"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ਬਲਗੇਰੀਅਨ"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ਇਤਾਲਵੀ"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ਡੈਨਿਸ਼"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ਨਾਰਵੇਜੀਅਨ"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ਫਿਨਿਸ਼"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"ਕਰੋਆਟੀਆਈ"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"ਚੈਕ"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"ਚੈੱਕ QWERTY ਸਟਾਈਲ"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"ਇਸਟੋਨੀਅਨ"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ਹੰਗੇਰੀਅਨ"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ਆਈਸਲੈਂਡੀ"</string>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index c3751197b7d2..61819b624112 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Niemiecki (Szwajcaria)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgijski"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bułgarski"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Włoski"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Duński"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norweski"</string>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index d6687c811a5b..665a1c7632f1 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemão suíço"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dinamarquês"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norueguês"</string>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 4f8a43279565..1ccc64409452 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemão (Suíça)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dinamarquês"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norueguês"</string>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index d6687c811a5b..665a1c7632f1 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemão suíço"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belga"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Búlgaro"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Dinamarquês"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norueguês"</string>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 1b38bdddd1a9..e0b488585c78 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Germană (Elveția)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgiană"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgară"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiană"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Daneză"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvegiană"</string>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 501517d34176..41ccf1a4f689 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"немецкий (Швейцария)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"нидерландский (Бельгия)"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"болгарский"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"итальянский"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"датский"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"норвежский"</string>
diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml
index c13661613bd5..4d355d73e985 100644
--- a/packages/InputDevices/res/values-si/strings.xml
+++ b/packages/InputDevices/res/values-si/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ස්විස් ජර්මන්"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"බෙල්ගියන්"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"බල්ගේරියානු"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ඉතාලි"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ඩෙන්මාර්ක"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"නෝර්වීජියානු"</string>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index 260a43258818..c7ff2fd5d994 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švajčiarske (nemčina)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgické"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bulharské"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"talianske"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"dánske"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"nórske"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"fínske"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"chorvátske"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"české"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Český štýl QWERTY"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"estónske"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"maďarské"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"islandské"</string>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 91ba472bde1e..68741b42e880 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"švicarska nemška"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belgijska"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bolgarska"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italijanska"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"danska"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norveška"</string>
diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml
index 3128025d6bd0..b3677cd699b4 100644
--- a/packages/InputDevices/res/values-sq/strings.xml
+++ b/packages/InputDevices/res/values-sq/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"gjermanishte zvicerane"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"belge"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"bullgarisht"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"italisht"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"danisht"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"norvegjisht"</string>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index 686f6aea8ce1..2f68903c4e2d 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"швајцарско немачка"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"белгијска"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"бугарска"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"италијанска"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"данска"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"норвешка"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"финска"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"хрватска"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"чешка"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Стил чешке QWERTY тастатуре"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"естонска"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"мађарска"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"исландска"</string>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index a4c0fcaa86de..b465fa64ce82 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Tyskt (Schweiz)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgiskt"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgariskt"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italienskt"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danskt"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norskt"</string>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 1e5c8d7d30e1..794d907f006d 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Kijerumani cha Uswisi"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Kibelgiji"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Kibulgaria"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Kiitaliano"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Kidenmarki"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Kinorwei"</string>
diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml
index e25e5edfda40..b75b57d5f358 100644
--- a/packages/InputDevices/res/values-ta/strings.xml
+++ b/packages/InputDevices/res/values-ta/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ஸ்விஸ் ஜெர்மன்"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"பெல்ஜியன்"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"பல்கேரியன்"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"இத்தாலியன்"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"டேனிஷ்"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"நார்வேஜியன்"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"ஃபின்னிஷ்"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"குரோஷியன்"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"செக்"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"செக் QWERTY நடை"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"எஸ்தோனியன்"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ஹங்கேரியன்"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ஐஸ்லாண்டிக்"</string>
diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml
index b6caafd48790..d40c3e0d5d9f 100644
--- a/packages/InputDevices/res/values-te/strings.xml
+++ b/packages/InputDevices/res/values-te/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"స్విస్ జర్మన్"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"బెల్జియన్"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"బల్గేరియన్"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"ఇటాలియన్"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"డేనిష్"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"నార్వేజియన్"</string>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 1170f8620a39..59136506abe0 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"เยอรมันสวิส"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"เบลเยียม"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"บัลแกเรีย"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"อิตาลี"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"เดนมาร์ก"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"นอร์เวย์"</string>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index 97b878bde52c..21ea5de903bd 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarian"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norwegian"</string>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 7e9b5e50fbc6..a89cea59b30f 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"İsviçre Almancası"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belçika dili"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgarca"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"İtalyanca"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Danca"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norveççe"</string>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index db5de4cb7a83..4b37ca954d37 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"німецька (Швейцарія)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"бельгійська"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"болгарська"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"італійська"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"данська"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"норвезька"</string>
diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml
index bf9e5adca553..ca42086b8811 100644
--- a/packages/InputDevices/res/values-ur/strings.xml
+++ b/packages/InputDevices/res/values-ur/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"سوئس جرمن"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"بیلجیئن"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"بلغاریائی"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"اطالوی"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"ڈینش"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"نارویجین"</string>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index 9d7f1e43e93f..77a06b5a4d79 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Nemis (Shveytsariya)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgiyancha"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bolgarcha"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italyancha"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Datcha"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Norvegcha"</string>
@@ -26,8 +28,7 @@
<string name="keyboard_layout_finnish" msgid="5585659438924315466">"Fincha"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Xorvatcha"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Chexcha"</string>
- <!-- no translation found for keyboard_layout_czech_qwerty (3331402534128515501) -->
- <skip />
+ <string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Chex QWERTY uslubi"</string>
<string name="keyboard_layout_estonian" msgid="8775830985185665274">"Estoncha"</string>
<string name="keyboard_layout_hungarian" msgid="4154963661406035109">"Vengercha"</string>
<string name="keyboard_layout_icelandic" msgid="5836645650912489642">"Islandcha"</string>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index eabaa1961946..fd570efe8693 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Tiếng Đức Thụy Sĩ"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Tiếng Bỉ"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Tiếng Bungary"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Tiếng Ý"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Tiếng Đan Mạch"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Tiếng Na Uy"</string>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index 3eb4b2c94a97..afc373acd61f 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"瑞士德语"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"比利时语"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"保加利亚语"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"意大利语"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"丹麦语"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"挪威语"</string>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 37cd533ca9b9..775fa2acfcec 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"德文(瑞士)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"比利時文"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"保加利亞文"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"意大利文"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"丹麥文"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"挪威文"</string>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index 8d2de40b2d86..b4a059cbeb1f 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"德文 (瑞士)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"比利時式"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"保加利亞文"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"義大利文"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"丹麥文"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"挪威文"</string>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index ddb688ad92e9..0a2499ad8967 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -19,6 +19,8 @@
<string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Isi-Swiss German"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Isi-Belgian"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Isi-Bulgarian"</string>
+ <!-- no translation found for keyboard_layout_bulgarian_phonetic (7568914730360106653) -->
+ <skip />
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Isi-Italian"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Isi-Danish"</string>
<string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Isi-Norwegian"</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/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 9ca1814783b5..0b4538097e41 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -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>
@@ -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-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 87f3b7a4f2e8..1ab88ed8e00e 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/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-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 5fc311af26b2..3373f815ebaf 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -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-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 904a70e73958..6e734bc873b8 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -487,7 +487,7 @@
<string name="status_unavailable" msgid="5279036186589861608">"मौजूद नहीं है"</string>
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"एमएसी पता रैंडम पर सेट है"</string>
<plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
- <item quantity="one">%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>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index fec2dd6d523f..d86d88b3345d 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -145,7 +145,7 @@
<string name="data_usage_ota" msgid="7984667793701597001">"Rendszerfrissítések"</string>
<string name="tether_settings_title_usb" msgid="3728686573430917722">"USB-megosztás"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"Hordozható hotspot"</string>
- <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Bluetooth megosztása"</string>
+ <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Bluetooth-megosztás"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Megosztás"</string>
<string name="tether_settings_title_all" msgid="8910259483383010470">"Megosztás és hotspot"</string>
<string name="managed_user_title" msgid="449081789742645723">"Összes munkaalkalmazás"</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-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 762d8304dd64..ee368fd5bfcf 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -143,9 +143,9 @@
<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>
- <string name="tether_settings_title_usb" msgid="3728686573430917722">"USB टेथर गर्दै"</string>
+ <string name="tether_settings_title_usb" msgid="3728686573430917722">"USB टेदर गर्दै"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"पोर्टेबल हटस्पट"</string>
- <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"ब्लुटुथ टेथर गर्दै"</string>
+ <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"ब्लुटुथ टेदर गर्दै"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"टेदर गर्दै"</string>
<string name="tether_settings_title_all" msgid="8910259483383010470">"टेदर गर्ने र पोर्टेबल हटस्पट"</string>
<string name="managed_user_title" msgid="449081789742645723">"कार्य प्रोफाइलका सबै एपहरू"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d2891a06402a..c5d70ac866b1 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -143,11 +143,11 @@
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Programu zilizoondolewa"</string>
<string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Watumiaji na programu ziilizoondolewa"</string>
<string name="data_usage_ota" msgid="7984667793701597001">"Masasisho ya mfumo"</string>
- <string name="tether_settings_title_usb" msgid="3728686573430917722">"Shiriki intaneti kwa USB"</string>
+ <string name="tether_settings_title_usb" msgid="3728686573430917722">"Sambaza mtandao kwa USB"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"Intaneti ya kusambazwa"</string>
- <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Shiriki intaneti kwa Bluetooth"</string>
- <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Inazuia"</string>
- <string name="tether_settings_title_all" msgid="8910259483383010470">"Kushiriki na kusambaza intaneti"</string>
+ <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Sambaza mtandao kwa Bluetooth"</string>
+ <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Kusambaza mtandao"</string>
+ <string name="tether_settings_title_all" msgid="8910259483383010470">"Kushiriki na kusambaza mtandao"</string>
<string name="managed_user_title" msgid="449081789742645723">"Programu zote za kazini"</string>
<string name="user_guest" msgid="6939192779649870792">"Mgeni"</string>
<string name="unknown" msgid="3544487229740637809">"Haijulikani"</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/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index defc33ee9233..7468d0450a7e 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -143,7 +143,7 @@
<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>
- <string name="tether_settings_title_usb" msgid="3728686573430917722">"ปล่อยสัญญาณผ่าน USB"</string>
+ <string name="tether_settings_title_usb" msgid="3728686573430917722">"เชื่อมต่อเน็ตผ่าน USB"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"ฮอตสปอตแบบพกพาได้"</string>
<string name="tether_settings_title_bluetooth" msgid="916519902721399656">"ปล่อยสัญญาณบลูทูธ"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"การปล่อยสัญญาณ"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 35bbbc0e8b39..34fdc1e45567 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -543,12 +543,13 @@ public class LocalBluetoothProfileManager {
mPbapProfile.setEnabled(device, true);
}
- if (mMapClientProfile != null) {
+ if ((mMapClientProfile != null)
+ && BluetoothUuid.containsAnyUuid(uuids, MapClientProfile.UUIDS)) {
profiles.add(mMapClientProfile);
removedProfiles.remove(mMapClientProfile);
}
- if ((mPbapClientProfile != null) && ArrayUtils.contains(localUuids, BluetoothUuid.PBAP_PCE)
+ if ((mPbapClientProfile != null)
&& BluetoothUuid.containsAnyUuid(uuids, PbapClientProfile.SRC_UUIDS)) {
profiles.add(mPbapClientProfile);
removedProfiles.remove(mPbapClientProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index 19cb2f59f321..4881a86b398a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -47,8 +47,6 @@ public final class MapClientProfile implements LocalBluetoothProfile {
private final LocalBluetoothProfileManager mProfileManager;
static final ParcelUuid[] UUIDS = {
- BluetoothUuid.MAP,
- BluetoothUuid.MNS,
BluetoothUuid.MAS,
};
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
index 0d54d7ee9b5c..28e993da7dc4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
@@ -72,6 +72,12 @@ public class MediaOutputSliceConstants {
"com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
/**
+ * An intent action to dismiss media output dialog.
+ */
+ public static final String ACTION_DISMISS_MEDIA_OUTPUT_DIALOG =
+ "com.android.systemui.action.DISMISS_MEDIA_OUTPUT_DIALOG";
+
+ /**
* Settings package name.
*/
public static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index dd2aa3bbbdf5..e7ec8b4e1f65 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -48,6 +48,8 @@ class SettingsProtoDumpUtil {
ConfigSettingsProto.ACTIVITY_MANAGER_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
ConfigSettingsProto.ACTIVITY_MANAGER_NATIVE_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ALARM_MANAGER,
+ ConfigSettingsProto.ALARM_MANAGER_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_APP_COMPAT,
ConfigSettingsProto.APP_COMPAT_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_AUTOFILL,
@@ -183,9 +185,6 @@ class SettingsProtoDumpUtil {
p.end(airplaneModeToken);
dumpSetting(s, p,
- Settings.Global.ALARM_MANAGER_CONSTANTS,
- GlobalSettingsProto.ALARM_MANAGER_CONSTANTS);
- dumpSetting(s, p,
Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED,
GlobalSettingsProto.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED);
dumpSetting(s, p,
@@ -2284,6 +2283,18 @@ class SettingsProtoDumpUtil {
SecureSettingsProto.Notification.IN_CALL_NOTIFICATION_ENABLED);
p.end(notificationToken);
+ final long oneHandedToken = p.start(SecureSettingsProto.ONEHANDED);
+ dumpSetting(s, p,
+ Settings.Secure.ONE_HANDED_MODE_ENABLED,
+ SecureSettingsProto.OneHanded.ONE_HANDED_MODE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
+ SecureSettingsProto.OneHanded.ONE_HANDED_MODE_TIMEOUT);
+ dumpSetting(s, p,
+ Settings.Secure.TAPS_APP_TO_EXIT,
+ SecureSettingsProto.OneHanded.TAPS_APP_TO_EXIT);
+ p.end(oneHandedToken);
+
final long parentalControlToken = p.start(SecureSettingsProto.PARENTAL_CONTROL);
dumpSetting(s, p,
Settings.Secure.PARENTAL_CONTROL_ENABLED,
@@ -2452,6 +2463,9 @@ class SettingsProtoDumpUtil {
p.end(soundsToken);
dumpSetting(s, p,
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ SecureSettingsProto.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
+ dumpSetting(s, p,
Settings.Secure.SYNC_PARENT_SOUNDS,
SecureSettingsProto.SYNC_PARENT_SOUNDS);
dumpSetting(s, p,
@@ -2572,22 +2586,6 @@ class SettingsProtoDumpUtil {
SecureSettingsProto.Zen.SETTINGS_SUGGESTION_VIEWED);
p.end(zenToken);
- dumpSetting(s, p,
- Settings.Secure.ONE_HANDED_MODE_ENABLED,
- SecureSettingsProto.OneHanded.ONE_HANDED_MODE_ENABLED);
-
- dumpSetting(s, p,
- Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
- SecureSettingsProto.OneHanded.ONE_HANDED_MODE_TIMEOUT);
-
- dumpSetting(s, p,
- Settings.Secure.TAPS_APP_TO_EXIT,
- SecureSettingsProto.OneHanded.TAPS_APP_TO_EXIT);
-
- dumpSetting(s, p,
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
- SecureSettingsProto.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
-
// Please insert new settings using the same order as in SecureSettingsProto.
p.end(token);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index d8f772d7f440..91510f65316f 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -117,7 +117,6 @@ public class SettingsBackupTest {
Settings.Global.AIRPLANE_MODE_ON,
Settings.Global.AIRPLANE_MODE_RADIOS,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
- Settings.Global.ALARM_MANAGER_CONSTANTS,
Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED,
Settings.Global.ALWAYS_FINISH_ACTIVITIES,
Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 190015cebe30..f5f58efb72e6 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -323,6 +323,9 @@
<!-- Permissions required for CTS test - AdbManagerTest -->
<uses-permission android:name="android.permission.MANAGE_DEBUGGING" />
+ <!-- Permission needed for CTS test - DisplayTest -->
+ <uses-permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
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/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4a55ce3f077b..556c39091cce 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Wys laeprioriteit-kennisgewingikone"</string>
<string name="other" msgid="429768510980739978">"Ander"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te wysig."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om by te voeg."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Verwyder <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Voeg <xliff:g id="TILE_NAME">%1$s</xliff:g> by posisie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g> na posisie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kitsinstellingswysiger."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-kennisgewing: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Maak instellings oop."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hou aan/af-skakelaar in om nuwe kontroles te sien"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Voeg kontroles by"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Wysig kontroles"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Voeg uitvoere by"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 toestel gekies"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> toestelle gekies"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ontkoppel)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kon nie koppel nie. Probeer weer."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7de4f443240c..c8462976528c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"አነስተኛ ቅድሚያ ያላቸው የማሳወቂያ አዶዎችን አሳይ"</string>
<string name="other" msgid="429768510980739978">"ሌላ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>፣ <xliff:g id="TILE_NAME">%2$s</xliff:g>። ለማርትዕ ሁለቴ መታ ያድርጉ።"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>። ለማከል ሁለቴ መታ ያድርጉ።"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ይውሰዱ"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ያስወግዱ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ወደ አቀማመጥ <xliff:g id="POSITION">%2$d</xliff:g> አክል"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ወደ አቀማመጥ <xliff:g id="POSITION">%2$d</xliff:g> አንቀሳቅስ"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"የፈጣን ቅንብሮች አርታዒ።"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"የ<xliff:g id="ID_1">%1$s</xliff:g> ማሳወቂያ፦ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ቅንብሮችን ክፈት።"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"አዲስ መቆጣጠሪያዎችን ለማየት የኃይል አዝራር ይያዙ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"መቆጣጠሪያዎችን አክል"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"መቆጣጠሪያዎችን ያርትዑ"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ውጽዓቶችን ያክሉ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ቡድን"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 መሣሪያ ተመርጧል"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> መሣሪያዎች ተመርጠዋል"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ግንኙነት ተቋርጧል)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ማገናኘት አልተቻለም። እንደገና ይሞክሩ።"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9874d70a87dc..785f8feb551a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -318,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>
@@ -697,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>
@@ -899,12 +899,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"إظهار رموز الإشعارات ذات الأولوية المنخفضة"</string>
<string name="other" msgid="429768510980739978">"غير ذلك"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. انقر مرّتين للتعديل."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. انقر مرّتين للإضافة."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"إزالة <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"إضافة <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"برنامج تعديل الإعدادات السريعة."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"إشعار <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"فتح الإعدادات."</string>
@@ -1091,4 +1099,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"اضغط مع الاستمرار على زر التشغيل لعرض عناصر التحكّم الجديدة."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"إضافة عناصر تحكّم"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"تعديل عناصر التحكّم"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"إضافة مخرجات"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"مجموعة"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"تم اختيار جهاز واحد."</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"تم اختيار <xliff:g id="COUNT">%1$d</xliff:g> جهاز."</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غير متّصل)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"تعذّر الاتصال. يُرجى إعادة المحاولة."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 55799a86089a..059c4bca8181 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"কম গুৰুত্বপূৰ্ণ জাননীৰ আইকনসমূহ দেখুৱাওক"</string>
<string name="other" msgid="429768510980739978">"অন্যান্য"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"অৱস্থান <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। সম্পাদনা কৰিবৰ বাবে দুবাৰ টিপক।"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। যোগ কৰিবলৈ দুবাৰ টিপক।"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> স্থানান্তৰ কৰক"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক আঁতৰাওক"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"এই স্থান <xliff:g id="POSITION">%2$d</xliff:g>ত <xliff:g id="TILE_NAME">%1$s</xliff:g> যোগ কৰক"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক এই স্থান <xliff:g id="POSITION">%2$d</xliff:g>লৈ যাওক"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ক্ষিপ্ৰ ছেটিংসমূহৰ সম্পাদক।"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> জাননী: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ছেটিংসমূহ খোলক।"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"নতুন নিয়ন্ত্ৰণসমূহ চাবলৈ পাৱাৰৰ বুটামটো ধৰি ৰাখক"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"নিয়ন্ত্ৰণসমূহ যোগ দিয়ক"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"নিয়ন্ত্ৰণসমূহ সম্পাদনা কৰক"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুটসমূহ যোগ দিয়ক"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"গোট"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১ টা ডিভাইচ বাছনি কৰা হৈছে"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> টা ডিভাইচ বাছনি কৰা হৈছে"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (সংযোগ বিচ্ছিন্ন হৈছে)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"সংযোগ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 83af4623b54c..2381d3330730 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Aşağı prioritet bildiriş işarələrini göstərin"</string>
<string name="other" msgid="429768510980739978">"Digər"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Redaktə etmək üçün iki dəfə tıklayın."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Əlavə etmək üçün iki dəfə tıklayın."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> silin"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="POSITION">%2$d</xliff:g> pozisiyasına <xliff:g id="TILE_NAME">%1$s</xliff:g> əlavə edin"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> pozisiyasına <xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sürətli ayarlar redaktoru."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildiriş: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları açın."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Yeni nizamlayıcıları görmək üçün yandırıb-söndürmə düyməsinə basıb saxlayın"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Nizamlayıcılar əlavə edin"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Nizamlayıcıları redaktə edin"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Nəticələri əlavə edin"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> cihaz seçilib"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlantı kəsilib)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Qoşulmaq alınmadı. Yenə cəhd edin."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihazı qoşalaşdırın"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index ce7b6077129f..55abfda98bc8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obaveštenja niskog prioriteta"</string>
<string name="other" msgid="429768510980739978">"Drugo"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite da biste izmenili."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dvaput dodirnite da biste dodali."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premesti pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Ukloni pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Dodajte „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premestite „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač za Brza podešavanja."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obaveštenja za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori Podešavanja."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zadržite dugme za uključivanje da biste videli nove kontrole"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Izmeni kontrole"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izabran je 1 uređaj"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Izabranih uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspelo. Probajte ponovo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index f1fc8f565a3b..47f9861f640b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -722,7 +722,7 @@
<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_automatic" msgid="5813109268050235275">"Сістэма сама будзе вызначаць, ці трэба для гэтага апавяшчэння ўключаць гук або вібрацыю"</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>
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Паказваць значкі апавяшчэнняў з нізкім прыярытэтам"</string>
<string name="other" msgid="429768510980739978">"Іншае"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Перамясціць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Выдаліць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Дадаць \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" у наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Перамясціць \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" у наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Рэдактар хуткіх налад."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Апавяшчэнне <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Адкрыць налады."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Каб убачыць новыя элементы кіравання, утрымлівайце кнопку сілкавання націснутай"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Дадаць элементы кіравання"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Змяніць элементы кіравання"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Дадайце прылады вываду"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрана 1 прылада"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Выбрана прылад: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (адключана)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не ўдалося падключыцца. Паўтарыце спробу."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 1678abadfeff..efe12673fe78 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Нека системата да определя дали дадено известие да се придружава от звук, или вибриране"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Показване на иконите за известията с нисък приоритет"</string>
<string name="other" msgid="429768510980739978">"Друго"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Докоснете двукратно, за да редактирате."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"„<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Докоснете двукратно, за да добавите."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Преместване на „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Премахване на „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Добавете „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместете „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор за бързи настройки."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известие от <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отваряне на настройките."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Задръжте бутона за захранване, за да видите новите контроли"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Добавяне на контроли"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Редактиране на контролите"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавяне на изходящи устройства"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 избрано устройство"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> избрани устройства"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (връзката е прекратена)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Неуспешно свързване. Опитайте отново."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9d5415fe5af1..fcdd286b6f55 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"কম-গুরুত্বপূর্ণ বিজ্ঞপ্তির আইকন দেখুন"</string>
<string name="other" msgid="429768510980739978">"অন্যান্য"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> লোকেশন, <xliff:g id="TILE_NAME">%2$s</xliff:g>৷ সম্পাদনা করতে দুবার আলতো চাপুন৷"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>৷ যোগ করতে দুবার আলতো চাপুন৷"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> সরান"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> সরান"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>-এ যোগ করুন"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>-এ সরান"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"দ্রুত সেটিংস সম্পাদক৷"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> বিজ্ঞপ্তি: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"সেটিংস খুলুন।"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"নতুন কন্ট্রোল দেখতে পাওয়ার বোতাম টিপে ধরে থাকুন"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুট যোগ করুন"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"গ্রুপ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g>টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (কানেক্ট করা নেই)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"কানেক্ট করা যায়নি। আবার চেষ্টা করুন।"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 819bfcf58674..811a971ab02b 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obavještenja niskog prioriteta"</string>
<string name="other" msgid="429768510980739978">"Ostalo"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput za uređivanje."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dodirnite dvaput za dodavanje."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pomjeri <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Ukloni <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Dodaj <xliff:g id="TILE_NAME">%1$s</xliff:g> na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g> na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivanje brzih postavki"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavještenje: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori postavke."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zadržite dugme za uključivanje da vidite nove kontrole"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je 1 uređaj"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Broj odabranih uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspjelo. Pokušajte ponovo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a7aff9850a6b..793c44b4544b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostra les icones de notificació amb prioritat baixa"</string>
<string name="other" msgid="429768510980739978">"Altres"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Suprimeix <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Afegeix <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuració ràpida."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificació de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Obre la configuració."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén premut el botó d\'engegada per veure controls nous"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Afegeix controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edita els controls"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Afegeix sortides"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositiu seleccionat"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"S\'han seleccionat <xliff:g id="COUNT">%1$d</xliff:g> dispositius"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconnectat)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No s\'ha pogut connectar. Torna-ho a provar."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 44864f0e8141..3f3d6be63f9c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -722,7 +722,7 @@
<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_automatic" msgid="5813109268050235275">"Nechat systém rozhodnout, zda má toto oznámení vydat zvuk či zavibrovat"</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>
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Zobrazit ikony oznámení s nízkou prioritou"</string>
<string name="other" msgid="429768510980739978">"Jiné"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvojitým klepnutím ji upravíte."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dlaždici přidáte dvojitým klepnutím."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Odstranit dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Přidat dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rychlého nastavení"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Oznámení aplikace <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otevřít nastavení."</string>
@@ -1013,7 +1021,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>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Nové ovládací prvky zobrazíte podržením vypínače"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Přidat ovládací prvky"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Upravit ovládací prvky"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Přidání výstupů"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Je vybráno 1 zařízení"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Vybraná zařízení: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojeno)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Spojení se nezdařilo. Zkuste to znovu."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b6702126323d..1d9238932283 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Få systemet til at afgøre, om denne notifikation skal vibrere eller afspille en lyd"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for notifikationer med lav prioritet"</string>
<string name="other" msgid="429768510980739978">"Andet"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryk to gange for at redigere."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tryk to gange for at tilføje."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Føj <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åbn Indstillinger."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold afbryderknappen nede for at se nye betjeningselementer"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Tilføj styring"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Rediger styring"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tilføj medieudgange"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Der er valgt 1 enhed"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Der er valgt <xliff:g id="COUNT">%1$d</xliff:g> enhed"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ingen forbindelse)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Der kunne ikke oprettes forbindelse. Prøv igen."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index af8d22ea4cd0..5976a1c95362 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Symbole für Benachrichtigungen mit einer niedrigen Priorität anzeigen"</string>
<string name="other" msgid="429768510980739978">"Sonstiges"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Zum Bearbeiten doppeltippen."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Zum Hinzufügen doppeltippen."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verschieben"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> entfernen"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> auf Position <xliff:g id="POSITION">%2$d</xliff:g> hinzufügen"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> auf Position <xliff:g id="POSITION">%2$d</xliff:g> verschieben"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor für Schnelleinstellungen."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Benachrichtigung von <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Einstellungen öffnen."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zum Anzeigen der Karten für neue Geräte Ein-/Aus-Taste gedrückt halten"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ausgabegeräte hinzufügen"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ein Gerät ausgewählt"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> Geräte ausgewählt"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nicht verbunden)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Verbindung nicht möglich. Versuch es noch einmal."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 951f01d54bdf..1eae5d4a12f9 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Επιτρέψτε στο σύστημα να αποφασίσει αν αυτή η ειδοποίηση θα αναπαράγει έναν ήχο ή θα ενεργοποιήσει τη δόνηση της συσκευής"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Εμφάνιση εικονιδίων ειδοποιήσεων χαμηλής προτεραιότητας"</string>
<string name="other" msgid="429768510980739978">"Άλλο"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Πατήστε δύο φορές για επεξεργασία."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Πατήστε δύο φορές για προσθήκη."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Κατάργηση <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Προσθήκη <xliff:g id="TILE_NAME">%1$s</xliff:g> στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g> στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Επεξεργασία γρήγορων ρυθμίσεων."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ειδοποίηση <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Άνοιγμα ρυθμίσεων."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Πατήστε το κουμπί λειτουργίας για να δείτε νέα στοιχεία ελέγχου."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Προσθήκη στοιχείων ελέγχου"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Επεξεργασία στοιχείων ελέγχου"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Προσθήκη εξόδων"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Ομάδα"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Επιλέχτηκε 1 συσκευή"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Επιλέχτηκαν <xliff:g id="COUNT">%1$d</xliff:g> συσκευές"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (αποσυνδέθηκε)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Δεν ήταν δυνατή η σύνδεση. Δοκιμάστε ξανά."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index debbd834f98d..4ea0341f8c39 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -879,12 +879,13 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string>
<string name="other" msgid="429768510980739978">"Other"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remove tile"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"add tile to end"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Move tile"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -1067,4 +1068,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold Power button to see new controls"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index b7ad5977e78f..3916e58ba076 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -879,12 +879,13 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string>
<string name="other" msgid="429768510980739978">"Other"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remove tile"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"add tile to end"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Move tile"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -1067,4 +1068,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold Power button to see new controls"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index debbd834f98d..4ea0341f8c39 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -879,12 +879,13 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string>
<string name="other" msgid="429768510980739978">"Other"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remove tile"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"add tile to end"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Move tile"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -1067,4 +1068,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold Power button to see new controls"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index debbd834f98d..4ea0341f8c39 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -879,12 +879,13 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string>
<string name="other" msgid="429768510980739978">"Other"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Add <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remove tile"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"add tile to end"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Move tile"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Add tile"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Move to <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Add to position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Position <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string>
@@ -1067,4 +1068,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold Power button to see new controls"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index c76dc72714de..7702337f080f 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -879,12 +879,13 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‎Show low-priority notification icons‎‏‎‎‏‎"</string>
<string name="other" msgid="429768510980739978">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎Other‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎Position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎. Double tap to edit.‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. Double tap to add.‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎Move ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎Remove ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎Add ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎Move ‎‏‎‎‏‏‎<xliff:g id="TILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎remove tile‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‏‎add tile to end‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‎Move tile‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎Add tile‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎Move to ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎Add to position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎Position ‎‏‎‎‏‏‎<xliff:g id="POSITION">%1$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎Quick settings editor.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ notification: ‎‏‎‎‏‏‎<xliff:g id="ID_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎Open settings.‎‏‎‎‏‎"</string>
@@ -1067,4 +1068,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎Hold Power button to see new controls‎‏‎‎‏‎"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎Add controls‎‏‎‎‏‎"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎Edit controls‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎Add outputs‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎Group‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎1 device selected‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="COUNT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ devices selected‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ (disconnected)‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎Couldn\'t connect. Try again.‎‏‎‎‏‎"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎Pair new device‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1ef965d22748..b1ee41f4c53c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -706,19 +706,19 @@
<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_automatic_title" msgid="3745465364578762652">"Automática"</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_automatic" msgid="5813109268050235275">"Dejar que el sistema determine si esta notificación debe emitir un sonido o una vibración"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar íconos de notificaciones con prioridad baja"</string>
<string name="other" msgid="429768510980739978">"Otros"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Quitar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Agregar <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de Configuración rápida"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir Configuración"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén presionado el botón de encendido para ver los nuevos controles"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Agregar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Agregar salidas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Se seleccionó 1 dispositivo"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Se seleccionaron <xliff:g id="COUNT">%1$d</xliff:g> dispositivos"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se pudo establecer la conexión. Vuelve a intentarlo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e483c0e1ac6d..7e5361b4f70c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -711,12 +711,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbuja"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</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_automatic" msgid="5813109268050235275">"Haz que el sistema determine si con esta notificación el dispositivo debe sonar o vibrar"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconos de notificaciones con prioridad baja"</string>
<string name="other" msgid="429768510980739978">"Otros"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dos veces para cambiarla."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dos veces para añadirlo."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Quitar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Añadir <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de ajustes rápidos."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir ajustes."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén pulsado el botón de encendido para ver los controles nuevos"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Añadir controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Añadir dispositivos de salida"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo seleccionado"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos seleccionados"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se ha podido conectar. Inténtalo de nuevo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular nuevo dispositivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index fea0df62e625..78de793517f4 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Kuva madala prioriteediga märguande ikoonid"</string>
<string name="other" msgid="429768510980739978">"Muu"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Asend <xliff:g id="POSITION">%1$d</xliff:g>, paan <xliff:g id="TILE_NAME">%2$s</xliff:g>. Topeltpuudutage muutmiseks."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Topeltpuudutage lisamiseks."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Paani <xliff:g id="TILE_NAME">%1$s</xliff:g> teisaldamine"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Paani <xliff:g id="TILE_NAME">%1$s</xliff:g> eemaldamine"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Lisage <xliff:g id="TILE_NAME">%1$s</xliff:g> asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Teisaldage <xliff:g id="TILE_NAME">%1$s</xliff:g> asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kiirseadete redigeerija."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Teenuse <xliff:g id="ID_1">%1$s</xliff:g> märguanne: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ava seaded."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Uute juhtelementide vaatamiseks hoidke all toitenuppu"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Lisa juhtelemente"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Muuda juhtelemente"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Väljundite lisamine"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 seade on valitud"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> seadet on valitud"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (pole ühendatud)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ühenduse loomine ebaõnnestus. Proovige uuesti."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 297472a66325..b5d84447271a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Erakutsi lehentasun txikiko jakinarazpenen ikonoak"</string>
<string name="other" msgid="429768510980739978">"Beste bat"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Editatzeko, sakatu birritan."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gehitzeko, sakatu birritan."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mugitu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Kendu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Gehitu <xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>garren postuan"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Eraman <xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>garren postura"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ezarpen bizkorren editorea."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> zerbitzuaren jakinarazpena: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ireki ezarpenak."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Eduki sakatuta etengailua kontrolatzeko aukera berriak ikusteko"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Gehitu irteerak"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Taldea"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 gailu hautatu da"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> gailu hautatu dira"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (deskonektatuta)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ezin izan da konektatu. Saiatu berriro."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2c32225d5ec2..d453f91da504 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"نمایش نمادهای اعلان کم‌اهمیت"</string>
<string name="other" msgid="429768510980739978">"موارد دیگر"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. برای ویرایش دو ضربه سریع بزنید."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. برای افزودن دو ضربه سریع بزنید."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"حذف <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"افزودن <xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ویرایشگر تنظیمات سریع."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"اعلان <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"باز کردن تنظیمات."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"برای دیدن کنترل‌های جدید، دکمه روشن/خاموش را پایین نگه دارید"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"افزودن کنترل‌ها"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ویرایش کنترل‌ها"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"افزودن خروجی"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"گروه"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"۱ دستگاه انتخاب شد"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> دستگاه انتخاب شد"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (اتصال قطع شد)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"متصل نشد. دوباره امتحان کنید."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b6c4ba0c2578..dde2449d8894 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Näytä vähemmän tärkeät ilmoituskuvakkeet"</string>
<string name="other" msgid="429768510980739978">"Muu"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Muokkaa kaksoisnapauttamalla."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lisää kaksoisnapauttamalla."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Poista <xliff:g id="TILE_NAME">%1$s</xliff:g>."</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g> kohtaan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g> kohtaan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Pika-asetusten muokkausnäkymä"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ilmoitus kohteesta <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Avaa asetukset."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Paina virtapainiketta pitkään nähdäksesi uudet säätimet"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Lisää säätimiä"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Muokkaa säätimiä"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lisää toistotapoja"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Ryhmä"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 laite valittu"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> laitetta valittu"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (yhteys katkaistu)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ei yhteyttä. Yritä uudelleen."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 34391efe460d..ea6de66db50f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification de faible priorité"</string>
<string name="other" msgid="429768510980739978">"Autre"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Touchez deux fois pour modifier."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Touchez deux fois pour ajouter."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Supprimer <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Ajouter <xliff:g id="TILE_NAME">%1$s</xliff:g> à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g> à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de paramètres rapides."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Maintenez enfoncé l\'interrupteur pour afficher les nouvelles commandes"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Un appareil sélectionné"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> appareil sélectionné"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index ebd9b9b9f40c..fc2691e3570d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification à faible priorité"</string>
<string name="other" msgid="429768510980739978">"Autre"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Appuyer deux fois pour modifier."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Appuyer deux fois pour ajouter."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Déplacer \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Supprimer \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Ajouter l\'élément \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Déplacer l\'élément \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de configuration rapide."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Appuyez de manière prolongée sur le bouton Marche/Arrêt pour afficher les nouvelles commandes"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 appareil sélectionné"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> appareils sélectionnés"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 79795927c1af..aba2d8fd389a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -711,12 +711,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbulla"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</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_automatic" msgid="5813109268050235275">"Fai que o sistema determine se a notificación debe emitir un son ou unha vibración"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconas das notificacións que teñan baixa prioridade"</string>
<string name="other" msgid="429768510980739978">"Outros"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dúas veces o elemento para editalo."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dúas veces o elemento para engadilo"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Elimina <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Engadir \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuración rápida."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configuración."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén premido o botón de acendido para ver os novos controis"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Engadir controis"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controis"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engadir saídas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Seleccionouse 1 dispositivo"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Seleccionáronse <xliff:g id="COUNT">%1$d</xliff:g> dispositivos"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (dispositivo desconectado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Non se puido establecer a conexión. Téntao de novo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 9599ca868365..1acef350034a 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -865,7 +865,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"ઓછી પ્રાધાન્યતાનું નોટિફિકેશન આઇકન બતાવો"</string>
<string name="other" msgid="429768510980739978">"અન્ય"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. સંપાદિત કરવા માટે બે વાર ટૅપ કરો."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ઉમેરવા માટે બે વાર ટૅપ કરો."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ખસેડો"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> દૂર કરો"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="POSITION">%2$d</xliff:g> જગ્યા પર <xliff:g id="TILE_NAME">%1$s</xliff:g>ને ઉમેરો"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> જગ્યા પર <xliff:g id="TILE_NAME">%1$s</xliff:g>ને ખસેડો"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ઝડપી સેટિંગ્સ સંપાદક."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> નોટિફિકેશન: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"સેટિંગ્સ ખોલો."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"નવા નિયંત્રણ જોવા માટે પાવર બટનને દબાવી રાખો"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"આઉટપુટ ઉમેરો"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ગ્રૂપ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ડિવાઇસ પસંદ કર્યું"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ડિવાઇસ પસંદ કર્યા"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ડિસ્કનેક્ટ થયેલું)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"કનેક્ટ કરી શકાયું નહીં. ફરી પ્રયાસ કરો."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f3a7ec1c0cca..1a69e81a8191 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -512,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>
@@ -713,12 +713,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"बबल"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"अपने-आप"</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_automatic" msgid="5813109268050235275">"सिस्टम को यह तय करने की अनुमति दें कि इस सूचना के मिलने पर आवाज़ हो या वाइब्रेशन हो"</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>
@@ -881,12 +881,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकता वाली सूचना के आइकॉन दिखाएं"</string>
<string name="other" msgid="429768510980739978">"अन्य"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. में बदलाव करने के लिए दो बार छूएं."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए दो बार छूएं."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को ले जाएं"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकालें"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काे क्रम संख्या <xliff:g id="POSITION">%2$d</xliff:g> पर जाेड़ें"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काे क्रम संख्या <xliff:g id="POSITION">%2$d</xliff:g> पर ले जाएं"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"त्वरित सेटिंग संपादक."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग खोलें."</string>
@@ -1069,4 +1077,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नए कंट्रोल देखने के लिए पावर बटन दबाकर रखें"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल मेन्यू में बदलाव करें"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोड़ें"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ग्रुप"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिवाइस चुना गया"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> डिवाइस चुने गए"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिसकनेक्ट किया गया)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट नहीं किया जा सका. फिर से कोशिश करें."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 870ca49add60..9b3f99748375 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obavijesti niskog prioriteta"</string>
<string name="other" msgid="429768510980739978">"Ostalo"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput da biste uredili."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dodirnite dvaput da biste dodali."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Ukloni <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Dodajte pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premjestite pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač brzih postavki."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavijest: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvaranje postavki."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zadržite tipku za uključivanje/isključivanje za prikaz novih kontrola"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodavanje izlaza"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je jedan uređaj"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Odabrano uređaja: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nije povezano)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije bilo moguće. Pokušajte ponovo."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f88076f54b22..7f4fa9d0acd3 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Alacsony prioritású értesítési ikonok mutatása"</string>
<string name="other" msgid="429768510980739978">"Egyéb"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció: <xliff:g id="TILE_NAME">%2$s</xliff:g>. Koppintson duplán a szerkesztéshez."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Koppintson duplán a hozzáadáshoz."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> eltávolítása"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> hozzáadása a következő pozícióhoz: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése a következő pozícióba: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Gyorsbeállítások szerkesztője"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-értesítések: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Beállítások megnyitása."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Az új vezérlők megtekintéséhez tartsa nyomva a bekapcsológombot"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Vezérlők hozzáadása"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Vezérlők szerkesztése"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Kimenetek hozzáadása"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Csoport"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 eszköz kiválasztva"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> eszköz kiválasztva"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (leválasztva)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Sikertelen csatlakozás. Próbálja újra."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 04c2bb1a5237..70cbf493feca 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -511,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Ցուցադրել ցածր առաջնահերթության ծանուցումների պատկերակները"</string>
<string name="other" msgid="429768510980739978">"Այլ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>: Կրկնակի հպեք՝ փոխելու համար:"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>: Կրկնակի հպեք՝ ավելացնելու համար:"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Տեղափոխել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Հեռացնել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Ավելացնել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը դիրք <xliff:g id="POSITION">%2$d</xliff:g>-ում"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը տեղափոխել դիրք <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Արագ կարգավորումների խմբագրիչ:"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ծանուցում՝ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Բացել կարգավորումները:"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Սեղմած պահեք սնուցման կոճակը՝ կառավարման նոր տարրերը տեսնելու համար։"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Ավելացնել կառավարման տարրեր"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Փոփոխել կառավարման տարրերը"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ավելացրեք մուտքագրման սարքեր"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Խումբ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ընտրված է 1 սարք"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Ընտրված է <xliff:g id="COUNT">%1$d</xliff:g> սարք"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (անջատված է)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Չհաջողվեց միանալ։ Նորից փորձեք։"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 403af01642dd..dc0a5128b808 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Tampilkan ikon notifikasi prioritas rendah"</string>
<string name="other" msgid="429768510980739978">"Lainnya"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ketuk dua kali untuk mengedit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ketuk dua kali untuk menambahkan."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Hapus <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Tambahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor setelan cepat."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifikasi <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka setelan."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Tahan Tombol daya untuk melihat kontrol baru"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Tambahkan kontrol"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit kontrol"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambahkan output"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 perangkat dipilih"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> perangkat dipilih"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (terputus)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak dapat terhubung. Coba lagi."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index a1c4a7f651c7..f79796b6276d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Sýna tákn fyrir tilkynningar með litlum forgangi"</string>
<string name="other" msgid="429768510980739978">"Annað"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Staða <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ýttu tvisvar til að breyta."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ýttu tvisvar til að bæta við."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Fjarlægja <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Bæta <xliff:g id="TILE_NAME">%1$s</xliff:g> við í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g> í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Flýtistillingaritill."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> tilkynning: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Opna stillingar."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Haltu aflrofanum inni til að sjá nýjar stýringar"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Bæta við stýringum"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Breyta stýringum"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Bæta við úttaki"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Hópur"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 tæki valið"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> tæki valin"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (aftengt)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tenging mistókst. Reyndu aftur."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index be017e11330a..3b99dc2e1f6e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Fai stabilire al sistema se questa notifica deve emettere suoni o vibrazioni"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostra icone di notifiche con priorità bassa"</string>
<string name="other" msgid="429768510980739978">"Altro"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Sposta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Rimuovi <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Aggiungi il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> alla posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Sposta il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> nella posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor di impostazioni rapide."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifica di <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Apri le impostazioni."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Tieni premuto il tasto di accensione per visualizzare i nuovi controlli"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Aggiungi controlli"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifica controlli"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Aggiungi uscite"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selezionato"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivi selezionati"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnesso)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossibile connettersi. Riprova."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 1baa627c5a7d..3bb8ea5fe1dd 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"הצגת סמלי התראות בעדיפות נמוכה"</string>
<string name="other" msgid="429768510980739978">"אחר"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. הקש פעמיים כדי לערוך."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. הקש פעמיים כדי להוסיף."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"הזזת <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"הסרת <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"הוספת <xliff:g id="TILE_NAME">%1$s</xliff:g> למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"העברת <xliff:g id="TILE_NAME">%1$s</xliff:g> למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"עורך הגדרות מהירות."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"התראות <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"פתיחת הגדרות."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ניתן ללחוץ על לחצן ההפעלה כדי להציג פקדים חדשים"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"הוספת פקדים"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"עריכת פקדים"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"הוספת מכשירי פלט"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"קבוצה"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"נבחר מכשיר אחד"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"נבחרו <xliff:g id="COUNT">%1$d</xliff:g> מכשירים"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (מנותק)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"לא ניתן היה להתחבר. יש לנסות שוב."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index fd1aa57f39d9..2c55569bb96a 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"優先度の低い通知アイコンを表示"</string>
<string name="other" msgid="429768510980739978">"その他"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> の <xliff:g id="TILE_NAME">%2$s</xliff:g> を編集するにはダブルタップします。"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を追加するにはダブルタップします。"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を移動します"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を削除します"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に追加"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に移動"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"クイック設定エディタ"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> の通知: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"設定を開きます。"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"電源ボタンを長押しすると、新しいコントロールが表示されます"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"コントロールを追加"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"コントロールを編集"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"出力の追加"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"グループ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"選択したデバイス: 1 台"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"選択したデバイス: <xliff:g id="COUNT">%1$d</xliff:g> 台"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(未接続)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"接続できませんでした。もう一度お試しください。"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 86451b8da7a5..ca5b7da19247 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"სისტემისთვის ისეთი უფლების მინიჭება, რომ მან განსაზღვროს, ამ შეტყობინებამ ხმოვანი სიგნალი უნდა აამოქმედოს თუ ვიბრაცია"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"დაბალი პრიორიტეტის მქონე შეტყობინებების ხატულების ჩვენება"</string>
<string name="other" msgid="429768510980739978">"სხვა"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. რედაქტირებისთვის, შეეხეთ ორმაგად."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. დასამატებლად, შეეხეთ ორმაგად."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის წაშლა"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის დამატება პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"სწრაფი პარამეტრების რედაქტორი."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> შეტყობინება: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"პარამეტრების გახსნა."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ხანგრძლივად დააჭირეთ ჩართვის ღილაკს მართვის ახალი საშუალებების სანახავად"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"მართვის საშუალებების დამატება"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"მართვის საშუალებათა რედაქტირება"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"მედია-გამოსავლების დამატება"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ჯგუფი"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"არჩეულია 1 მოწყობილობა"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"არჩეულია <xliff:g id="COUNT">%1$d</xliff:g> მოწყობილობა"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (კავშირი გაწყვეტილია)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"დაკავშირება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index ed6c05d60bb6..a4bf498edfff 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>
@@ -419,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>
@@ -711,14 +711,14 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Көпіршік"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Автоматты"</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_automatic" msgid="5813109268050235275">"Хабарландыру дыбысының немесе дірілдің қосылуын жүйе анықтайтын болады"</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>
@@ -774,7 +774,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Маңызды емес хабарландыру белгішелерін көрсету"</string>
<string name="other" msgid="429768510980739978">"Басқа"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> орны, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Өңдеу үшін екі рет түртіңіз."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Қосу үшін екі рет түртіңіз."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жылжыту"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жою"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> бөлшегін <xliff:g id="POSITION">%2$d</xliff:g>-позицияға енгізу"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> бөлшегін <xliff:g id="POSITION">%2$d</xliff:g>-позицияға жылжыту"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Жылдам параметрлер өңдегіші."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> хабарландыруы: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Параметрлерді ашу."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Жаңа басқару элементтерін көру үшін \"Қуат\" түймесін басып тұрыңыз."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Басқару элементтерін енгізу"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Басқару элементтерін өзгерту"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Шығыс сигналдарды қосу"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 құрылғы таңдалды."</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> құрылғы таңдалды."</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылған)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Қосылмады. Қайта қосылып көріңіз."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғыны жұптау"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 7636fdd6d8c2..7eaa3039947a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -419,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>
@@ -774,7 +774,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"បង្ហាញ​រូប​ការជូនដំណឹង​ដែលមានអាទិភាពទាប"</string>
<string name="other" msgid="429768510980739978">"ផ្សេងៗ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>, ប៉ះពីរដងដើម្បីកែ"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, ប៉ះពីរដងដើម្បីបន្ថែម"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"យក <xliff:g id="TILE_NAME">%1$s</xliff:g> ចេញ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"បញ្ចូល <xliff:g id="TILE_NAME">%1$s</xliff:g> ទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g> ទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"កម្មវិធីកែការកំណត់រហ័ស"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ការជូនដំណឹង៖ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"បើកការកំណត់"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"សង្កត់​ប៊ូតុង​ថាមពល ដើម្បី​មើលឃើញ​ការគ្រប់គ្រង​ថ្មីៗ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"បញ្ចូល​ផ្ទាំងគ្រប់គ្រង"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"កែ​ផ្ទាំងគ្រប់គ្រង"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"បញ្ចូល​ឧបករណ៍​មេឌៀ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ក្រុម"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"បានជ្រើសរើស​ឧបករណ៍ 1"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"បានជ្រើសរើស​ឧបករណ៍ <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (បាន​ផ្ដាច់)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"មិន​អាច​ភ្ជាប់​បាន​ទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គង​ឧបករណ៍ថ្មី"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 7980790c3feb..79f845290365 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"ಕಡಿಮೆ-ಆದ್ಯತೆ ಸೂಚನೆಯ ಐಕಾನ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="other" msgid="429768510980739978">"ಇತರ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ಸ್ಥಳ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ಎಡಿಟ್ ಮಾಡಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ಸೇರಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಸರಿಸಿ"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ತೆಗೆದುಹಾಕಿ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="POSITION">%2$d</xliff:g> ಗೆ ಸೇರಿಸಿ"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="POSITION">%2$d</xliff:g> ಗೆ ಸರಿಸಿ"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳ ಎಡಿಟರ್."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ಅಧಿಸೂಚನೆ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ಹೊಸ ನಿಯಂತ್ರಣಗಳನ್ನು ನೋಡಲು ಪವರ್ ಬಟನ್ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ನಿಯಂತ್ರಣಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ಔಟ್‌ಪುಟ್‌ಗಳನ್ನು ಸೇರಿಸಿ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ಗುಂಪು"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ಸಾಧನವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ಸಾಧನಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ce59c6f796c5..6a755e52f058 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"시스템에서 알림 시 소리 또는 진동을 사용할지 결정하도록 허용합니다."</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"우선순위가 낮은 알림 아이콘 표시"</string>
<string name="other" msgid="429768510980739978">"기타"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"위치 <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. 수정하려면 두 번 탭하세요."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. 추가하려면 두 번 탭하세요."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 이동"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 삭제"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>에 추가"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>(으)로 이동"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"빠른 설정 편집기"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 알림: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"설정 열기"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"새 컨트롤을 보려면 전원 버튼을 길게 누르세요."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"컨트롤 추가"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"컨트롤 수정"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"출력 추가"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"그룹"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"기기 1대 선택됨"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"기기 <xliff:g id="COUNT">%1$d</xliff:g>대 선택됨"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(연결 끊김)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"연결할 수 없습니다. 다시 시도하세요."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 57132e43dae9..a740d07f7eac 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Билдирменин үнүн чыгартууну же басууну тутумга тапшырыңыз"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string>
<string name="other" msgid="429768510980739978">"Башка"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дегенди жылдыруу"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дегенди алып салуу"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> плиткасы <xliff:g id="POSITION">%2$d</xliff:g>-позицияга кошулсун"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> плиткасы <xliff:g id="POSITION">%2$d</xliff:g>-позицияга кошулсун"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ыкчам жөндөөлөр түзөткүчү."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> эскертмеси: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Жөндөөлөрдү ачуу."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Башкаруу элементтерин көрүү үчүн күйгүзүү/өчүрүү баскычын коё бербей басып туруңуз"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Башкаруу элементтерин кошуу"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Башкаруу элементтерин түзөтүү"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Медиа түзмөктөрдү кошуу"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 түзмөк тандалды"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> түзмөк тандалды"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылды)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Байланышпай койду. Кайталоо."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0ff4509891b0..1fb2ca0b0bd2 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"ສະແດງໄອຄອນການແຈ້ງເຕືອນຄວາມສຳຄັນຕ່ຳ"</string>
<string name="other" msgid="429768510980739978">"ອື່ນໆ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອແກ້ໄຂ."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອເພີ່ມ."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"ລຶບ <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"ເພີ່ມ <xliff:g id="TILE_NAME">%1$s</xliff:g> ໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g> ໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ຕົວແກ້ໄຂການຕັ້ງຄ່າດ່ວນ"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"ການແຈ້ງເຕືອນ <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ເປີດການຕັ້ງຄ່າ."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ກົດປຸ່ມເປີດປິດຄ້າງໄວ້ເພື່ອເບິ່ງການຄວບຄຸມໃໝ່"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ເພີ່ມການຄວບຄຸມ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ແກ້ໄຂການຄວບຄຸມ"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ເພີ່ມເອົ້າພຸດ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ກຸ່ມ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ເລືອກ 1 ອຸປະກອນແລ້ວ"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"ເລືອກ <xliff:g id="COUNT">%1$d</xliff:g> ອຸປະກອນແລ້ວ"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ຕັດການເຊື່ອມຕໍ່ແລ້ວ)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້. ລອງໃໝ່."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 239151ac5be4..bd24722436dd 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -784,7 +784,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>
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Rodyti mažo prioriteto pranešimų piktogramas"</string>
<string name="other" msgid="429768510980739978">"Kita"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis, išklotinės elementas „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Dukart palieskite, kad redaguotumėte."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Dukart palieskite, kad pridėtumėte."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Pašalinti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Pridėti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sparčiųjų nustatymų redagavimo priemonė."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"„<xliff:g id="ID_1">%1$s</xliff:g>“ pranešimas: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atidaryti nustatymus."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Jei norite peržiūrėti naujus valdiklius, laikykite paspaudę maitinimo mygtuką"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Pridėti valdiklių"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Redaguoti valdiklius"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Išvesčių pridėjimas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupė"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Pasirinktas 1 įrenginys"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Pasirinkta įrenginių: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"„<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ (atjungta)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepavyko prijungti. Bandykite dar kartą."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 1552a9e68363..e8d9a4d8c797 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -714,7 +714,7 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbulis"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automātiski"</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>
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Rādīt zemas prioritātes paziņojumu ikonas"</string>
<string name="other" msgid="429768510980739978">"Citi"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Lai rediģētu, veiciet dubultskārienu."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lai pievienotu, veiciet dubultskārienu."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pārvietot elementu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Noņemt elementu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Pievienot elementu “<xliff:g id="TILE_NAME">%1$s</xliff:g>” <xliff:g id="POSITION">%2$d</xliff:g>. pozīcijā"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Pārvietot elementu “<xliff:g id="TILE_NAME">%1$s</xliff:g>” uz <xliff:g id="POSITION">%2$d</xliff:g>. pozīciju"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ātro iestatījumu redaktors."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> paziņojums: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atvērt iestatījumus."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Nospiediet barošanas pogu un turiet to, lai skatītu jaunas vadīklas"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Pievienot vadīklas"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Rediģēt vadīklas"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Izejas ierīču pievienošana"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Atlasīta viena ierīce"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Atlasītas vairākas ierīces (kopā <xliff:g id="COUNT">%1$d</xliff:g>)"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (savienojums pārtraukts)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nevarēja izveidot savienojumu. Mēģiniet vēlreiz."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 42b758fd518b..164cb96bf046 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -711,14 +711,14 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Балонче"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Автоматски"</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_automatic" msgid="5813109268050235275">"Дозволете системот да определи дали известувањево треба да испушти звук или да вибрира"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Прикажувај икони за известувања со низок приоритет"</string>
<string name="other" msgid="429768510980739978">"Друго"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Место <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Допрете двапати за уредување."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Допрете двапати за додавање."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Отстранете <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Додајте <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицијата <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицијата <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уредник за брзи поставки."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известување од <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отворете ги поставките."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Задржете го копчето за вклучување за да ги видите новите контроли"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Додајте контроли"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Изменете ги контролите"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излези"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Избран е 1 уред"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Избрани се <xliff:g id="COUNT">%1$d</xliff:g> уреди"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (исклучен)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не можеше да се поврзе. Обидете се повторно."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 2e68d3b8717d..ba379d3b7116 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"പ്രാധാന്യം കുറഞ്ഞ അറിയിപ്പ് ചിഹ്‌നങ്ങൾ"</string>
<string name="other" msgid="429768510980739978">"മറ്റുള്ളവ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. എഡിറ്റുചെയ്യുന്നതിന് രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ചേർക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കംചെയ്യുക"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="POSITION">%2$d</xliff:g> സ്ഥാനത്തേയ്ക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> ചേർക്കുക"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> സ്ഥാനത്തേയ്ക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ദ്രുത ക്രമീകരണ എഡിറ്റർ."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> അറിയിപ്പ്: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ക്രമീകരണം തുറക്കുക."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"പുതിയ നിയന്ത്രണങ്ങൾ കാണാൻ പവർ ബട്ടൺ പിടിക്കുക"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"നിയന്ത്രണങ്ങൾ എഡിറ്റ് ചെയ്യുക"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ഔട്ട്പുട്ടുകൾ ചേർക്കുക"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ഗ്രൂപ്പ്"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ഒരു ഉപകരണം തിരഞ്ഞെടുത്തു"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ഉപകരണങ്ങൾ തിരഞ്ഞെടുത്തു"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (വിച്ഛേദിച്ചു)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"കണക്റ്റ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index fab7a5531ca1..56c5ef27baec 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -711,7 +711,7 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Бөмбөлөг"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Автомат"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Бага ач холбогдолтой мэдэгдлийн дүрс тэмдгийг харуулах"</string>
<string name="other" msgid="429768510980739978">"Бусад"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Байршил <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Засахын тулд 2 удаа дарна уу."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Нэмэхийн тулд 2 удаа дарна уу."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г зөөх"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г устгах"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г <xliff:g id="POSITION">%2$d</xliff:g> байрлалд нэмэх"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г байрлал <xliff:g id="POSITION">%2$d</xliff:g> руу зөөх"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Түргэн тохиргоо засварлагч."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Тохиргоог нээнэ үү."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Шинэ хяналтыг харахын тулд асаах товчийг удаан дарна уу"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Хяналт нэмэх"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Хяналтыг өөрчлөх"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Гаралт нэмэх"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Бүлэг"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 төхөөрөмж сонгосон"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> төхөөрөмж сонгосон"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (салсан)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Холбогдож чадсангүй. Дахин оролдоно уу."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 31a0a7a8da31..728065fbd5cc 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"कमी प्राधान्य सूचना आयकन दर्शवा"</string>
<string name="other" msgid="429768510980739978">"अन्य"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करण्यासाठी दोनदा टॅप करा."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> . जोडण्यासाठी दोनदा टॅप करा."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> हलवा"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काढा"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> स्थानावर जोडा"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> स्थानावर हलवा"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिंग्ज संपादक."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग्ज उघडा."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नवीन नियंत्रणे पाहण्यासाठी पॉवर बटण धरून ठेवा"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"नियंत्रणे जोडा"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे व्यवस्थापित करा"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोडा"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> डिव्हाइस निवडली आहेत"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट केले)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट करू शकलो नाही. पुन्हा प्रयत्न करा."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b147b6e7a023..62d845c3f72a 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Tunjukkan ikon pemberitahuan keutamaan rendah"</string>
<string name="other" msgid="429768510980739978">"Lain-lain"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dwiketik untuk mengedit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dwiketik untuk menambah."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Alih keluar <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Tambahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> pada kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor tetapan pantas."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Pemberitahuan <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka tetapan."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Tahan butang Kuasa untuk melihat kawalan baharu"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Tambah kawalan"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edit kawalan"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambah output"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Kumpulan"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 peranti dipilih"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> peranti dipilih"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (diputuskan sambungan)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak boleh menyambung. Cuba lagi."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 636e83643ee6..e72f16925eab 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"အရေးမကြီးသော အကြောင်းကြားချက် သင်္ကေတများ ပြရန်"</string>
<string name="other" msgid="429768510980739978">"အခြား"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>၊ <xliff:g id="TILE_NAME">%2$s</xliff:g> နေရာ။ တည်းဖြတ်ရန် နှစ်ချက်တို့ပါ။"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>။ ပေါင်းထည့်ရန် နှစ်ချက်တို့ပါ။"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုရွှေ့ပါ"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုဖယ်ရှားပါ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို အနေအထား <xliff:g id="POSITION">%2$d</xliff:g> သို့ ပေါင်းထည့်ရန်"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို အနေအထား <xliff:g id="POSITION">%2$d</xliff:g> သို့ ရွှေ့ရန်"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"မြန်ဆန်သည့် ဆက်တင်တည်းဖြတ်စနစ်"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> အကြောင်းကြားချက် − <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ဆက်တင်များကို ဖွင့်ပါ။"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ထိန်းချုပ်မှုအသစ်များ ကြည့်ရန် ဖွင့်ပိတ်ခလုတ်ကို ဖိထားပါ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ထိန်းချုပ်မှုများ ထည့်ရန်"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ တည်းဖြတ်ရန်"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"မီဒီယာအထွက်များ ထည့်ရန်"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"စက်ပစ္စည်း <xliff:g id="COUNT">%1$d</xliff:g> ခုကို ရွေးချယ်ထားသည်"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ချိတ်ဆက်မထားပါ)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ချိတ်ဆက်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 93ef3af9b037..41aabcb89b65 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for varsler med lav prioritet"</string>
<string name="other" msgid="429768510980739978">"Annet"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dobbelttrykk for å endre."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dobbelttrykk for å legge til."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Legg til <xliff:g id="TILE_NAME">%1$s</xliff:g> i posisjon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g> til posisjon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsvindu for hurtiginnstillinger."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-varsel: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åpne innstillingene."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Hold inne av/på-knappen for å se kontroller"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Legg til kontroller"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Endre kontroller"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Legg til utenheter"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet er valgt"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> enheter er valgt"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frakoblet)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kunne ikke koble til. Prøv på nytt."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d218e3939304..0cf09d2bdd0d 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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकताका सूचना आइकनहरू देखाउनुहोस्"</string>
<string name="other" msgid="429768510980739978">"अन्य"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नाका लागि डबल ट्याप गर्नुहोस्।"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई सार्नुहोस्"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई हटाउनुहोस्"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई <xliff:g id="POSITION">%2$d</xliff:g> स्थितिमा थप्नुहोस्"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई <xliff:g id="POSITION">%2$d</xliff:g> स्थितिमा सार्नुहोस्"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिङ सम्पादक।"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> को सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिङहरूलाई खोल्नुहोस्।"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नयाँ नियन्त्रण सुविधाहरू हेर्न पावर बटन थिचिराख्नुहोस्"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"नियन्त्रण सुविधाहरू सम्पादन गर्नु…"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट यन्त्रहरू थप्नुहोस्"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> वटा यन्त्र चयन गरिए"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट गरिएको)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ यन्त्रको जोडा बनाउनुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3d61ee4adaf7..49e097e5a047 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -711,12 +711,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Bubbel"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automatisch"</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_automatic" msgid="5813109268050235275">"Het systeem laten bepalen of deze melding geluid moet maken of moet trillen"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Pictogrammen voor meldingen met lage prioriteit weergeven"</string>
<string name="other" msgid="429768510980739978">"Overig"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Positie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te bewerken."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om toe te voegen."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verwijderen"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> toevoegen aan positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen naar positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor voor \'Snelle instellingen\'."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-melding: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Instellingen openen."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Houd de aan/uit-knop ingedrukt om nieuwe bedieningselementen te bekijken"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Bedieningselementen toevoegen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Bedieningselementen bewerken"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Uitvoer toevoegen"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Eén apparaat geselecteerd"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> apparaten geselecteerd"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (verbinding verbroken)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kan geen verbinding maken. Probeer het nog eens."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index dc38e39e054c..c3105ff55bc7 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"ଏହି ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ ହେବା ସମୟରେ ସାଉଣ୍ଡ ହେବା ଉଚିତ ନା ଭାଇବ୍ରେସନ୍ ତାହା ସିଷ୍ଟମକୁ ସ୍ଥିର କରିବାକୁ ଦିଅନ୍ତୁ"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"କମ୍‍-ଅଗ୍ରାଧିକାର ବିଜ୍ଞପ୍ତି ଆଇକନ୍‍ ଦେଖାନ୍ତୁ"</string>
<string name="other" msgid="429768510980739978">"ଅନ୍ୟାନ୍ୟ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ଅବସ୍ଥାନ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ଏଡିଟ୍ କରିବାକୁ ଡବଲ୍‍-ଟାପ୍‍ କରନ୍ତୁ।"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ଯୋଡ଼ିବା ପାଇଁ ଡବଲ୍‍-ଟାପ୍‍ କରନ୍ତୁ।"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ନିଅନ୍ତୁ"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ବାହାର କରିଦିଅନ୍ତୁ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="POSITION">%2$d</xliff:g> ଅବସ୍ଥାନକୁ <xliff:g id="TILE_NAME">%1$s</xliff:g> ଯୋଡନ୍ତୁ"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> ଅବସ୍ଥାନକୁ <xliff:g id="TILE_NAME">%1$s</xliff:g> ଘୁଞ୍ଚାନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଏଡିଟର୍।"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ବିଜ୍ଞପ୍ତି: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ସେଟିଂସ୍ ଖୋଲନ୍ତୁ।"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ନୂଆ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ଆଉଟପୁଟ୍ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ଗୋଷ୍ଠୀ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g>ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 8d15d176ead4..b12dfb3954ee 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੇ ਸੂਚਨਾ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਦਿਖਾਓ"</string>
<string name="other" msgid="429768510980739978">"ਹੋਰ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਤਬਦੀਲ ਕਰੋ"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਹਟਾਓ"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਾਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਾਨ \'ਤੇ ਲਿਜਾਓ"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਸੰਪਾਦਕ।"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ਸੂਚਨਾ: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ਨਵੇਂ ਕੰਟਰੋਲ ਦੇਖਣ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ਆਊਟਪੁੱਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"ਗਰੁੱਪ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ਡੀਵਾਈਸ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ਡੀਵਾਈਸਾਂ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ਡਿਸਕਨੈਕਟ ਹੋਇਆ)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b531be0ff724..d195977f460b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Pokazuj ikony powiadomień o niskim priorytecie"</string>
<string name="other" msgid="429768510980739978">"Inne"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>, kafelek <xliff:g id="TILE_NAME">%2$s</xliff:g>. Kliknij dwukrotnie, by edytować."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>. Kliknij dwukrotnie, by dodać."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Usuń kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Dodaj kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> w położeniu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> w położenie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Edytor szybkich ustawień."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Powiadomienie z aplikacji <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otwórz ustawienia."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Przytrzymaj przycisk zasilania, by zobaczyć nowe elementy sterujące"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj elementy sterujące"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Edytuj elementy sterujące"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodaj urządzenia wyjściowe"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Wybrano 1 urządzenie"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Wybrane urządzenia: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (rozłączono)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nie udało się połączyć. Spróbuj ponownie."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 67f161151d47..6f96f37bc302 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -712,13 +712,13 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</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_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string>
<string name="other" msgid="429768510980739978">"Outros"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantenha o botão liga/desliga pressionado para ver os novos controles"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 6e32ca4b940b..93999f6b7b49 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se esta notificação deve emitir um som ou uma vibração"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de prioridade baixa"</string>
<string name="other" msgid="429768510980739978">"Outro"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de definições rápidas."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir as definições."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantenha premido o botão ligar/desligar para ver os novos controlos."</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controlos"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controlos"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicione saídas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desligado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível ligar. Tente novamente."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 67f161151d47..6f96f37bc302 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -712,13 +712,13 @@
<string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</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_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string>
<string name="other" msgid="429768510980739978">"Outros"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Remove <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Adicionar <xliff:g id="TILE_NAME">%1$s</xliff:g> à posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mantenha o botão liga/desliga pressionado para ver os novos controles"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> dispositivos selecionados"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 691fd835b563..9810cc5540cb 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Afișați pictogramele de notificare cu prioritate redusă"</string>
<string name="other" msgid="429768510980739978">"Altele"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Atingeți de două ori pentru a edita."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Atingeți de două ori pentru a adăuga."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Eliminați <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Adăugați <xliff:g id="TILE_NAME">%1$s</xliff:g> pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g> pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editorul pentru setări rapide."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificare <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Deschideți setările."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Apăsați butonul de alimentare pentru a vedea noile comenzi"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Adăugați comenzi"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editați comenzile"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adăugați ieșiri"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"S-a selectat un dispozitiv"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"S-au selectat <xliff:g id="COUNT">%1$d</xliff:g> dispozitive"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (s-a deconectat)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nu s-a putut conecta. Reîncercați."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 3ccafda2bbfe..9f43b5ac7f16 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -722,7 +722,7 @@
<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_automatic" msgid="5813109268050235275">"Система будет сама определять, включать ли звуковой сигнал или вибрацию для уведомления"</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>
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Показывать значки уведомлений с низким приоритетом"</string>
<string name="other" msgid="429768510980739978">"Другое"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, кнопка \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Чтобы изменить, нажмите дважды."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\". Чтобы добавить, нажмите дважды."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Переместить кнопку \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Удалить кнопку \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Добавить значок <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Переместить значок <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор быстрых настроек."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Уведомление <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Открыть настройки."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Удерживайте кнопку питания, чтобы увидеть новые элементы управления"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Добавить виджеты"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Изменить виджеты"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавление устройств вывода"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Группа"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрано 1 устройство"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Выбрано устройств: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (отключено)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не удалось подключиться. Повторите попытку."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 14528c078a33..700f5101475c 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"අඩු ප්‍රමුඛතා දැනුම්දීම් අයිකන පෙන්වන්න"</string>
<string name="other" msgid="429768510980739978">"වෙනත්"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. වෙනස් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. එක් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ගෙන යන්න"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ඉවත් කරන්න"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> තත්ත්වයට <xliff:g id="POSITION">%2$d</xliff:g> එක් කරන්න"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> තත්ත්වයට <xliff:g id="POSITION">%2$d</xliff:g> ගෙන යන්න"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ඉක්මන් සැකසුම් සංස්කාරකය."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> දැනුම්දීම: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"සැකසීම් විවෘත කරන්න."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"නව පාලන බැලීමට බල බොත්තම අල්ලාගෙන සිටින්න"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"පාලන එක් කරන්න"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"පාලන සංස්කරණය කරන්න"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ප්‍රතිදාන එක් කරන්න"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"සමූහය"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"උපාංග 1ක් තෝරන ලදී"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"උපාංග <xliff:g id="COUNT">%1$d</xliff:g>ක් තෝරන ලදී"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (විසන්ධි විය)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"සම්බන්ධ වීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 3c405128788a..62df35aeee02 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Zobraziť ikony upozornení s nízkou prioritou"</string>
<string name="other" msgid="429768510980739978">"Ďalšie"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Upravíte ju dvojitým klepnutím."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Pridáte ju dvojitým klepnutím."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Presunúť dlaždicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Odstrániť dlaždicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Pridať <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Presunúť <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rýchlych nastavení"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Upozornenie <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvoriť nastavenia"</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Pridržaním vypínača zobrazíte nové ovládacie prvky"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Pridať ovládače"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Upraviť ovládače"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Pridanie výstupov"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 vybrané zariadenie"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Počet vybraných zariadení: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojené)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepodarilo sa pripojiť. Skúste to znova."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4c68eeb15800..25bdd656b56c 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>
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Pokaži ikone obvestil z nizko stopnjo prednosti"</string>
<string name="other" msgid="429768510980739978">"Drugo"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Če želite urediti, se dvakrat dotaknite."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Če želite dodati, se dvakrat dotaknite."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premik tega: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Odstranitev tega: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Dodaj ploščico <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premakni ploščico <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Urejevalnik hitrih nastavitev."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obvestilo za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Odpri nastavitve."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Za ogled novih kontrolnikov pridržite gumb za vklop"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrolnike"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrolnike"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajanje izhodov"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Izbranih je toliko naprav: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (povezava prekinjena)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezave ni bilo mogoče vzpostaviti. Poskusite znova."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 681fa3fbeaf1..abcde4286190 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Shfaq ikonat e njoftimeve me përparësi të ulët"</string>
<string name="other" msgid="429768510980739978">"Të tjera"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Trokit dy herë për ta redaktuar."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Trokit dy herë për ta shtuar."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Zhvendose <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Hiqe <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Shto <xliff:g id="TILE_NAME">%1$s</xliff:g> te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Zhvendos <xliff:g id="TILE_NAME">%1$s</xliff:g> te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redaktori i cilësimeve të shpejta."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Njoftim nga <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Hap cilësimet."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Mbaj shtypur butonin e energjisë për të parë kontrollet e reja"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Shto kontrollet"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Modifiko kontrollet"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Shto daljet"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupi"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 pajisje e zgjedhur"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> pajisje të zgjedhura"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (e shkëputur)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nuk mund të lidhej. Provo sërish."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 15190d4860bf..e117602afa9a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -884,12 +884,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Прикажи иконе обавештења ниског приоритета"</string>
<string name="other" msgid="429768510980739978">"Друго"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двапут додирните да бисте изменили."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двапут додирните да бисте додали."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Премести плочицу <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Уклони плочицу <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Додајте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позицију <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместите „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позицију <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уређивач за Брза подешавања."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Обавештења за <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отвори Подешавања."</string>
@@ -1073,4 +1081,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Задржите дугме за укључивање да бисте видели нове контроле"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Додај контроле"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Измени контроле"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излазе"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Изабран је 1 уређај"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Изабраних уређаја: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (веза је прекинута)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Повезивање није успело. Пробајте поново."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6fc976ea9d36..8559b0b0de2b 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Visa ikoner för aviseringar med låg prioritet"</string>
<string name="other" msgid="429768510980739978">"Annat"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryck snabbt två gånger för att redigera positionen."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lägg till genom att trycka snabbt två gånger."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Ta bort <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Lägg till <xliff:g id="TILE_NAME">%1$s</xliff:g> på position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g> till position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigerare för snabbinställningar."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-avisering: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Öppna inställningarna."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"De nya snabbkontrollerna visas om du håller strömbrytaren nedtryckt"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Lägg till snabbkontroller"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Redigera snabbkontroller"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lägg till utgångar"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet har valts"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> enheter har valts"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frånkopplad)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Det gick inte att ansluta. Försök igen."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 67d5f3404269..76b86eee8289 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Onyesha aikoni za arifa zisizo muhimu"</string>
<string name="other" msgid="429768510980739978">"Nyingine"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Gusa mara mbili ili ubadilishe."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gusa mara mbili ili uongeze."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Hamisha <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Ondoa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Ongeza <xliff:g id="TILE_NAME">%1$s</xliff:g> kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Sogeza <xliff:g id="TILE_NAME">%1$s</xliff:g> kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kihariri cha Mipangilio ya haraka."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Arifa kutoka <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Fungua mipangilio."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Shikilia kitufe cha kuwasha/kuzima ili uone vidhibiti vipya"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Weka vidhibiti"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Badilisha vidhibiti"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Weka vifaa vya kutoa sauti"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Kikundi"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Umechagua kifaa 1"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Umechagua vifaa <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (hakijaunganishwa)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Imeshindwa kuunganisha. Jaribu tena."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 8f2e296301d7..9d5c54fc7890 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"குறைந்த முன்னுரிமை உள்ள அறிவிப்பு ஐகான்களைக் காட்டு"</string>
<string name="other" msgid="429768510980739978">"மற்றவை"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. திருத்த, இருமுறை தட்டவும்."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. சேர்க்க, இருமுறை தட்டவும்."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தவும்"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ அகற்றவும்"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"நிலைப்பாடு <xliff:g id="POSITION">%2$d</xliff:g> இல் <xliff:g id="TILE_NAME">%1$s</xliff:g>ஐச் சேர்க்கும்"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"நிலைப்பாடு <xliff:g id="POSITION">%2$d</xliff:g>க்கு <xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தும்"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"விரைவு அமைப்புகள் திருத்தி."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> அறிவிப்பு: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"அமைப்புகளைத் திற."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"புதிய கட்டுப்பாடுகளைப் பார்க்க பவர் பட்டனைப் பிடித்திருக்கவும்"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"கட்டுப்பாடுகளைச் சேர்த்தல்"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுதல்"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"அவுட்புட்களைச் சேர்த்தல்"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"குழு"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 சாதனம் தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> சாதனங்கள் தேர்ந்தெடுக்கப்பட்டுள்ளன"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (இணைப்பு துண்டிக்கப்பட்டது)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"இணைக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 8a15d7615140..925c958199ed 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -693,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"తక్కువ ప్రాధాన్యత నోటిఫికేషన్ చిహ్నాలను చూపించు"</string>
<string name="other" msgid="429768510980739978">"ఇతరం"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. సవరించడానికి రెండుసార్లు నొక్కండి."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. జోడించడానికి రెండుసార్లు నొక్కండి."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలిస్తుంది"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తీసివేస్తుంది"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి <xliff:g id="TILE_NAME">%1$s</xliff:g>ని జోడించండి"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి <xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలించండి"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"శీఘ్ర సెట్టింగ్‌ల ఎడిటర్."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> నోటిఫికేషన్: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"సెట్టింగ్‌లను తెరవండి."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"కొత్త నియంత్రణలను చూడడానికి పవర్ బటన్‌ని నొక్కి పట్టుకోండి"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"నియంత్రణలను జోడించండి"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"నియంత్రణలను ఎడిట్ చేయండి"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"అవుట్‌పుట్‌లను జోడించండి"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"గ్రూప్"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 పరికరం ఎంచుకోబడింది"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> పరికరాలు ఎంచుకోబడ్డాయి"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (డిస్‌కనెక్ట్ అయ్యింది)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"కనెక్ట్ చేయడం సాధ్యపడలేదు. మళ్లీ ట్రై చేయండి."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 16593b4c245f..c613e9c0d7c0 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>
@@ -337,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>
@@ -509,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>
@@ -706,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_automatic_title" msgid="3745465364578762652">"อัตโนมัติ"</string>
@@ -862,7 +862,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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"แสดงไอคอนการแจ้งเตือนลำดับความสำคัญต่ำ"</string>
<string name="other" msgid="429768510980739978">"อื่นๆ"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> <xliff:g id="TILE_NAME">%2$s</xliff:g> แตะ 2 ครั้งเพื่อแก้ไข"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> แตะ 2 ครั้งเพื่อเพิ่ม"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"นำ <xliff:g id="TILE_NAME">%1$s</xliff:g> ออก"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"เพิ่ม <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ตัวแก้ไขการตั้งค่าด่วน"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> การแจ้งเตือน: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"เปิดการตั้งค่า"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"กดปุ่มเปิด/ปิดค้างไว้เพื่อดูตัวควบคุมใหม่ๆ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"เพิ่มตัวควบคุม"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"แก้ไขตัวควบคุม"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"เพิ่มเอาต์พุต"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"กลุ่ม"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"เลือกอุปกรณ์ไว้ 1 รายการ"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"เลือกอุปกรณ์ไว้ <xliff:g id="COUNT">%1$d</xliff:g> รายการ"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ยกเลิกการเชื่อมต่อแล้ว)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"เชื่อมต่อไม่ได้ ลองใหม่"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 283a6d54ef0f..9411957e56f2 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Ipakita ang mga icon ng notification na may mababang priority"</string>
<string name="other" msgid="429768510980739978">"Iba pa"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. I-double tap upang i-edit."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. I-double tap upang idagdag."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Alisin ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Idagdag ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyong <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyong <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor ng Mga mabilisang setting."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification sa <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buksan ang mga setting."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Pindutin nang matagal ang Power button para makita ang mga bagong kontrol"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Magdagdag ng mga kontrol"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Mag-edit ng mga kontrol"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Magdagdag ng mga output"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device ang napili"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> (na) device ang napili"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nakadiskonekta)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Hindi makakonekta. Subukan ulit."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 514f4ee57ce3..4d46f93e2d25 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Düşük öncelikli bildirim simgelerini göster"</string>
<string name="other" msgid="429768510980739978">"Diğer"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. konum, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Düzenlemek için iki kez dokunun."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Eklemek için iki kez dokunun."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusunu taşı"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusunu kaldır"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="TILE_NAME">%1$s</xliff:g> öğesini <xliff:g id="POSITION">%2$d</xliff:g> konumuna ekle"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> öğesini <xliff:g id="POSITION">%2$d</xliff:g> konumuna taşı"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Hızlı ayar düzenleyicisi."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirimi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları aç."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Yeni kontrolleri görmek için Güç düğmesini basılı tutun"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Denetim ekle"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Denetimleri düzenle"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Çıkışlar ekleyin"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> cihaz seçildi"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlı değil)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Bağlanılamadı. Tekrar deneyin."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 565907ce9106..399b53a91de6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -889,12 +889,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Показувати значки сповіщень із низьким пріоритетом"</string>
<string name="other" msgid="429768510980739978">"Інше"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двічі торкніться, щоб змінити."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двічі торкніться, щоб додати."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Видалити <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Додати <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор швидких налаштувань."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Сповіщення <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Відкрити налаштування."</string>
@@ -1079,4 +1087,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Утримуйте кнопку живлення, щоб переглянути нові елементи керування"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Додати елементи керування"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Змінити елементи керування"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додати пристрої виводу"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Вибрано 1 пристрій"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Вибрано пристроїв: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (відключено)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не вдалося підключитися. Повторіть спробу."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d5f90195a4d9..09e500d227a6 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"کم ترجیحی اطلاع کے آئیکنز دکھائیں"</string>
<string name="other" msgid="429768510980739978">"دیگر"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>۔ ترمیم کرنے کیلئے دو بار تھپتھپائیں۔"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>۔ شامل کرنے کیلئے دو بار تھپتھپائیں۔"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو منتقل کریں"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹائیں"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"پوزیشن <xliff:g id="TILE_NAME">%1$s</xliff:g> میں <xliff:g id="POSITION">%2$d</xliff:g> شامل کریں"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو پوزیشن <xliff:g id="POSITION">%2$d</xliff:g> میں منتقل کریں"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"فوری ترتیبات کا ایڈیٹر۔"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> اطلاع: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ترتیبات کھولیں۔"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"نئے کنٹرولز دیکھنے کے لیے پاور بٹن کو دبائے رکھیں"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"کنٹرولز شامل کریں"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"کنٹرولز میں ترمیم کریں"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"آؤٹ پٹس شامل کریں"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"گروپ"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 آلہ منتخب کیا گیا"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> آلات منتخب کیے گئے"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غیر منسلک ہو گیا)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"منسلک نہیں ہو سکا۔ پھر کوشش کریں۔"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 71703e05ea29..61b91c768582 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Muhim boʻlmagan bildirishnoma ikonkalarini koʻrsatish"</string>
<string name="other" msgid="429768510980739978">"Boshqa"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>-joy, “<xliff:g id="TILE_NAME">%2$s</xliff:g>” tugmasi. Tahrirlash uchun ustiga ikki marta bosing."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi. Qo‘shish uchun ustiga ikki marta bosing."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasini ko‘chirish"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"<xliff:g id="TILE_NAME">%1$s</xliff:g> tugmasini olib tashlash"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"<xliff:g id="POSITION">%2$d</xliff:g>-joyga buni qo‘shish: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g>-joyga buni ko‘chirish: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Tezkor sozlamalar muharriri"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirishnomasi: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Sozlamalarni ochish."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Yangi boshqaruv elementlari bilan tanishish uchun quvvat tugmasini bosib turing"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Element kiritish"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Elementlarni tahrirlash"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Chiquvchi qurilmani kiritish"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Guruh"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ta qurilma tanlandi"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> ta qurilma tanlandi"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (uzilgan)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ulanmadi. Qayta urining."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 12eb5e12f2a6..dc2a5b826439 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Hiển thị biểu tượng thông báo có mức ưu tiên thấp"</string>
<string name="other" msgid="429768510980739978">"Khác"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Nhấn đúp để chỉnh sửa."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Nhấn đúp để thêm."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Xóa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Thêm <xliff:g id="TILE_NAME">%1$s</xliff:g> vào vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g> đến vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Trình chỉnh sửa cài đặt nhanh."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Thông báo của <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Mở phần cài đặt."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Giữ nút Nguồn để xem các tùy chọn điều khiển mới"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Thêm các tùy chọn điều khiển"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Chỉnh sửa tùy chọn điều khiển"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Thêm thiết bị đầu ra"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Nhóm"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Đã chọn 1 thiết bị"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"Đã chọn <xliff:g id="COUNT">%1$d</xliff:g> thiết bị"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (đã ngắt kết nối)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Không thể kết nối. Hãy thử lại."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f886ecb6cf39..71a7d8e7165d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"显示低优先级的通知图标"</string>
<string name="other" msgid="429768510980739978">"其他"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移动<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"将“<xliff:g id="TILE_NAME">%1$s</xliff:g>”添加到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"将“<xliff:g id="TILE_NAME">%1$s</xliff:g>”移动到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快捷设置编辑器。"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"打开设置。"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"按住电源按钮即可查看新控件"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"添加控件"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"修改控件"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"添加输出设备"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"群组"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已选择 1 个设备"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已选择 <xliff:g id="COUNT">%1$d</xliff:g> 个设备"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(已断开连接)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"无法连接。请重试。"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 744d341deb08..1d763d010984 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -716,7 +716,7 @@
<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_automatic" msgid="5813109268050235275">"由系統判斷是否要讓此通知發出音效或震動"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string>
<string name="other" msgid="429768510980739978">"其他"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕按兩下即可編輯。"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕按兩下即可新增。"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"將「<xliff:g id="TILE_NAME">%1$s</xliff:g>」加去位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"將「<xliff:g id="TILE_NAME">%1$s</xliff:g>」移去位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯工具。"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"按住「開關」按鈕以查看新控制項"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 部裝置"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 49d530f0a7af..303ddd925a86 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -711,7 +711,7 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"泡泡"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"自動"</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>
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string>
<string name="other" msgid="429768510980739978">"其他"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕觸兩下即可編輯。"</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕觸兩下即可新增。"</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 新增到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 移到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯器。"</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"按住電源按鈕即可查看新的控制項"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 部裝置"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index abc45c84ccd0..d8eb7ade9600 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -879,12 +879,20 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Bonisa izithonjana zesaziso zokubaluleka okuncane"</string>
<string name="other" msgid="429768510980739978">"Okunye"</string>
- <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Thepha kabili ukuze uhlele."</string>
- <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Thepha kabili ukuze ungeze."</string>
- <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_remove_tile" msgid="3406781901949899624">"Susa i-<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add" msgid="6289879620154587233">"Engeza i-<xliff:g id="TILE_NAME">%1$s</xliff:g> ukuze ubeke i-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g> ukuze ubeke i-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
+ <!-- no translation found for accessibility_qs_edit_remove_tile_action (775511891457193480) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_action (5051211910345301833) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_move (2009373939914517817) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_start_add (7560798153975555772) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_move_to_position (5198161544045930556) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_tile_add_to_position (9029163095148274690) -->
+ <skip />
+ <!-- no translation found for accessibility_qs_edit_position (4509277359815711830) -->
+ <skip />
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Isihleli sezilungiselelo ezisheshayo."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> isaziso: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Vula izilungiselelo."</string>
@@ -1067,4 +1075,11 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Bamba Inkinobho yamandla ukuze ubone izilawuli ezintsha"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Engeza Izilawuli"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Hlela izilawuli"</string>
+ <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engeza okukhiphayo"</string>
+ <string name="media_output_dialog_group" msgid="5571251347877452212">"Iqembu"</string>
+ <string name="media_output_dialog_single_device" msgid="3102758980643351058">"idivayisi ekhethiwe e-1"</string>
+ <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"amadivayisi akhethiwe angu-<xliff:g id="COUNT">%1$d</xliff:g>"</string>
+ <string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (inqamukile)"</string>
+ <string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ayikwazanga ukuxhumeka. Zama futhi."</string>
+ <string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhanqa idivayisi entsha"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 41158296fa57..b62ea6bc2ff6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -15,8 +15,6 @@
*/
package com.android.keyguard;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
@@ -401,14 +399,9 @@ public class KeyguardSecurityContainer extends FrameLayout {
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// Consume bottom insets because we're setting the padding locally (for IME and navbar.)
- int inset;
- if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- int bottomInset = insets.getInsetsIgnoringVisibility(systemBars()).bottom;
- int imeInset = insets.getInsets(ime()).bottom;
- inset = max(bottomInset, imeInset);
- } else {
- inset = insets.getSystemWindowInsetBottom();
- }
+ int bottomInset = insets.getInsetsIgnoringVisibility(systemBars()).bottom;
+ int imeInset = insets.getInsets(ime()).bottom;
+ int inset = max(bottomInset, imeInset);
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), inset);
return insets.inset(0, 0, 0, inset);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 77afa27b5cca..bde9a6e7c714 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -52,6 +52,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
import java.util.List;
@@ -64,7 +65,7 @@ import javax.inject.Provider;
*/
@SysUISingleton
public class AuthController extends SystemUI implements CommandQueue.Callbacks,
- AuthDialogCallback, DozeReceiver {
+ AuthDialogCallback, DozeReceiver, KeyguardBouncer.BouncerExpansionCallback {
private static final String TAG = "AuthController";
private static final boolean DEBUG = true;
@@ -426,6 +427,35 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog = null;
}
+ /** See {@link KeyguardBouncer.BouncerExpansionCallback#onFullyShown}. */
+ @Override
+ public void onFullyShown() {
+ if (mUdfpsController != null) {
+ mUdfpsController.setBouncerVisibility(true);
+ }
+ }
+
+ /** See {@link KeyguardBouncer.BouncerExpansionCallback#onStartingToHide}. */
+ @Override
+ public void onStartingToHide() {
+ }
+
+ /** See {@link KeyguardBouncer.BouncerExpansionCallback#onStartingToShow}. */
+ @Override
+ public void onStartingToShow() {
+ if (mUdfpsController != null) {
+ mUdfpsController.setBouncerVisibility(true);
+ }
+ }
+
+ /** See {@link KeyguardBouncer.BouncerExpansionCallback#onFullyHidden}. */
+ @Override
+ public void onFullyHidden() {
+ if (mUdfpsController != null) {
+ mUdfpsController.setBouncerVisibility(false);
+ }
+ }
+
private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
mCurrentDialogArgs = args;
final @BiometricAuthenticator.Modality int type = args.argi1;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index ba78485438ea..d79c96ea4774 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -86,7 +86,13 @@ class UdfpsController implements DozeReceiver {
// Default non-HBM backlight value normalized to the range [0, 1.0]. Used as a fallback when the
// actual brightness value cannot be retrieved.
private final float mDefaultBrightness;
+ // Indicates whether the overlay is currently showing. Even if it has been requested, it might
+ // not be showing.
private boolean mIsOverlayShowing;
+ // Indicates whether the overlay has been requested.
+ private boolean mIsOverlayRequested;
+ // Indicates whether the bouncer is showing. When it is showing, the overlay needs to be hidden.
+ private boolean mIsBouncerShowing;
// The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
// to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -98,12 +104,12 @@ class UdfpsController implements DozeReceiver {
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@Override
public void showUdfpsOverlay() {
- UdfpsController.this.showUdfpsOverlay();
+ UdfpsController.this.setShowOverlay(true);
}
@Override
public void hideUdfpsOverlay() {
- UdfpsController.this.hideUdfpsOverlay();
+ UdfpsController.this.setShowOverlay(false);
}
@Override
@@ -207,6 +213,35 @@ class UdfpsController implements DozeReceiver {
mView.dozeTimeTick();
}
+ private void setShowOverlay(boolean show) {
+ if (show == mIsOverlayRequested) {
+ return;
+ }
+ mIsOverlayRequested = show;
+ updateOverlay();
+ }
+
+ /**
+ * Call when the visibility of the bouncer changes.
+ *
+ * @param isShowing Whether or not the bouncer is showing
+ */
+ void setBouncerVisibility(boolean isShowing) {
+ if (isShowing == mIsBouncerShowing) {
+ return;
+ }
+ mIsBouncerShowing = isShowing;
+ updateOverlay();
+ }
+
+ private void updateOverlay() {
+ if (mIsOverlayRequested && !mIsBouncerShowing) {
+ showUdfpsOverlay();
+ } else {
+ hideUdfpsOverlay();
+ }
+ }
+
private void showUdfpsOverlay() {
mFgExecutor.execute(() -> {
if (!mIsOverlayShowing) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index f98bb333b6b1..ec60cbd175d0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -16,15 +16,12 @@
package com.android.systemui.bubbles;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.graphics.PixelFormat.TRANSPARENT;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -48,7 +45,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Point;
import android.graphics.Rect;
@@ -471,11 +467,7 @@ public class BubbleExpandedView extends LinearLayout {
mKeyboardVisible = false;
mNeedsNewHeight = false;
if (mActivityView != null) {
- if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- setImeWindowToDisplay(0, 0);
- } else {
- mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0));
- }
+ setImeWindowToDisplay(0, 0);
}
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
Log.d(TAG, "onDetachedFromWindow: bubble=" + getBubbleKey());
@@ -525,13 +517,7 @@ public class BubbleExpandedView extends LinearLayout {
insets.getDisplayCutout() != null
? insets.getDisplayCutout().getSafeInsetBottom()
: 0);
- final int insetsBottom = Math.max(activityViewBottom - keyboardTop, 0);
-
- if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- setImeWindowToDisplay(getWidth(), insetsBottom);
- } else {
- mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
- }
+ setImeWindowToDisplay(getWidth(), Math.max(activityViewBottom - keyboardTop, 0));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 424a8246b278..6154a4ecb85c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -198,6 +198,22 @@ public class DozeLog implements Dumpable {
}
/**
+ * Appends doze state changed sent to all DozeMachine parts event to the logs
+ * @param state new DozeMachine state
+ */
+ public void traceDozeStateSendComplete(DozeMachine.State state) {
+ mLogger.logStateChangedSent(state);
+ }
+
+ /**
+ * Appends display state changed event to the logs
+ * @param displayState new DozeMachine state
+ */
+ public void traceDisplayState(int displayState) {
+ mLogger.logDisplayStateChanged(displayState);
+ }
+
+ /**
* Appends wake-display event to the logs.
* @param wake if we're waking up or sleeping.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index 732745a1158b..46cec95a967a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -143,6 +143,22 @@ class DozeLogger @Inject constructor(
})
}
+ fun logStateChangedSent(state: DozeMachine.State) {
+ buffer.log(TAG, INFO, {
+ str1 = state.name
+ }, {
+ "Doze state sent to all DozeMachineParts stateSent=$str1"
+ })
+ }
+
+ fun logDisplayStateChanged(displayState: Int) {
+ buffer.log(TAG, INFO, {
+ int1 = displayState
+ }, {
+ "Display state changed to $int1"
+ })
+ }
+
fun logWakeDisplay(isAwake: Boolean) {
buffer.log(TAG, DEBUG, {
bool1 = isAwake
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index d5820f3e05e4..1e0460bea5be 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -205,6 +205,7 @@ public class DozeMachine {
}
void onScreenState(int state) {
+ mDozeLog.traceDisplayState(state);
for (Part part : mParts) {
part.onScreenState(state);
}
@@ -308,6 +309,7 @@ public class DozeMachine {
for (Part p : mParts) {
p.transitionTo(oldState, newState);
}
+ mDozeLog.traceDozeStateSendComplete(newState);
switch (newState) {
case FINISH:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 5aeb8df2028d..92494cf5b546 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -35,6 +35,7 @@ import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
import com.android.systemui.util.sensors.AsyncSensorManager;
+import java.io.PrintWriter;
import java.util.Optional;
import javax.inject.Inject;
@@ -221,4 +222,9 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
mDebugBrightnessBucket = intent.getIntExtra(BRIGHTNESS_BUCKET, -1);
updateBrightnessAndReady(false /* force */);
}
+
+ /** Dump current state */
+ public void dump(PrintWriter pw) {
+ pw.println("DozeScreenBrightnessSensorRegistered=" + mRegistered);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java
index 1b20cfbc4e55..3da6caf31968 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java
@@ -16,7 +16,10 @@
package com.android.systemui.keyguard;
+import androidx.annotation.NonNull;
+
import java.util.ArrayList;
+import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -26,8 +29,8 @@ public class Lifecycle<T> {
private ArrayList<T> mObservers = new ArrayList<>();
- public void addObserver(T observer) {
- mObservers.add(observer);
+ public void addObserver(@NonNull T observer) {
+ mObservers.add(Objects.requireNonNull(observer));
}
public void removeObserver(T observer) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
index fc2016913292..702be72ff4ed 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java
@@ -171,6 +171,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/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index 72cd4f1343e6..cf45f52e3367 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/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/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index 419d8d590124..52ce7fe210ec 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -219,7 +219,7 @@ public class PipAnimationController {
public void onAnimationEnd(Animator animation) {
mCurrentValue = mEndValue;
final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
- onEndTransaction(mLeash, tx);
+ onEndTransaction(mLeash, tx, mTransitionDirection);
if (mPipAnimationCallback != null) {
mPipAnimationCallback.onPipAnimationEnd(tx, this);
}
@@ -319,7 +319,8 @@ public class PipAnimationController {
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {}
- void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {}
+ void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
+ @TransitionDirection int transitionDirection) {}
abstract void applySurfaceControlTransaction(SurfaceControl leash,
SurfaceControl.Transaction tx, float fraction);
@@ -426,13 +427,20 @@ public class PipAnimationController {
}
@Override
- void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
+ void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
+ int transitionDirection) {
// NOTE: intentionally does not apply the transaction here.
// this end transaction should get executed synchronously with the final
// WindowContainerTransaction in task organizer
- getSurfaceTransactionHelper()
- .resetScale(tx, leash, getDestinationBounds())
- .crop(tx, leash, getDestinationBounds());
+ final Rect destBounds = getDestinationBounds();
+ getSurfaceTransactionHelper().resetScale(tx, leash, destBounds);
+ if (transitionDirection == TRANSITION_DIRECTION_LEAVE_PIP) {
+ // Leaving to fullscreen, reset crop to null.
+ tx.setPosition(leash, destBounds.left, destBounds.top);
+ tx.setWindowCrop(leash, 0, 0);
+ } else {
+ getSurfaceTransactionHelper().crop(tx, leash, destBounds);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index b6334c562a02..6cc0cd879d71 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -62,6 +62,7 @@ import com.android.internal.os.SomeArgs;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.pip.phone.PipMenuActivityController;
import com.android.systemui.pip.phone.PipUpdateThread;
+import com.android.systemui.pip.phone.PipUtils;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
@@ -260,6 +261,11 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mSplitScreenOptional = splitScreenOptional;
mTaskOrganizer = shellTaskOrganizer;
+
+ if (!PipUtils.hasSystemFeature(context)) {
+ Log.w(TAG, "Device not support PIP feature");
+ return;
+ }
mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED);
displayController.addDisplayWindowListener(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
index 5bb179484e5d..8a2e9e23343c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
@@ -18,7 +18,6 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
@@ -30,7 +29,6 @@ import android.app.IActivityManager;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -278,9 +276,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mContext = context;
mActivityManager = ActivityManager.getService();
- PackageManager pm = context.getPackageManager();
- boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
- if (supportsPip) {
+ if (PipUtils.hasSystemFeature(mContext)) {
initController(context, broadcastDispatcher, configController, deviceConfig,
displayController, floatingContentCoordinator, sysUiState, pipBoundsHandler,
pipSurfaceTransactionHelper, pipTaskOrganizer, pipUiEventLogger);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
index baa8f118f362..1bf6dd7bb9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
@@ -18,6 +18,7 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
@@ -57,4 +58,14 @@ public class PipUtils {
}
return new Pair<>(null, 0);
}
+
+ /**
+ * The util to check if device has PIP feature
+ *
+ * @param context application context
+ * @return true if device has PIP feature, false otherwise.
+ */
+ public static boolean hasSystemFeature(Context context) {
+ return context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsViewController.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsViewController.java
index 4ecd52f8adf5..2f4df1fcbe20 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsViewController.java
@@ -36,6 +36,8 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import javax.inject.Inject;
+
/**
* Controller for {@link PipControlsView}.
*/
@@ -108,7 +110,7 @@ public class PipControlsViewController {
}
};
-
+ @Inject
public PipControlsViewController(PipControlsView view, Optional<Pip> pipOptional,
LayoutInflater layoutInflater, @Main Handler handler) {
super();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/dagger/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/pip/tv/dagger/TvPipModule.java
new file mode 100644
index 000000000000..e8e392069ea7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/dagger/TvPipModule.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.tv.dagger;
+
+import android.app.Activity;
+import android.content.Context;
+
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.pip.Pip;
+import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSurfaceTransactionHelper;
+import com.android.systemui.pip.PipTaskOrganizer;
+import com.android.systemui.pip.PipUiEventLogger;
+import com.android.systemui.pip.tv.PipController;
+import com.android.systemui.pip.tv.PipMenuActivity;
+import com.android.systemui.pip.tv.PipNotification;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import java.util.Optional;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+/**
+ * Dagger module for TV Pip.
+ */
+@Module(subcomponents = {TvPipComponent.class})
+public abstract class TvPipModule {
+
+ /** Inject into PipMenuActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(PipMenuActivity.class)
+ public abstract Activity providePipMenuActivity(PipMenuActivity activity);
+
+ @SysUISingleton
+ @Provides
+ static Pip providePipController(Context context,
+ BroadcastDispatcher broadcastDispatcher,
+ PipBoundsHandler pipBoundsHandler,
+ PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
+ PipTaskOrganizer pipTaskOrganizer) {
+ return new PipController(context, broadcastDispatcher, pipBoundsHandler,
+ pipSurfaceTransactionHelper, pipTaskOrganizer);
+ }
+
+ @SysUISingleton
+ @Provides
+ static PipNotification providePipNotification(Context context,
+ BroadcastDispatcher broadcastDispatcher,
+ PipController pipController) {
+ return new PipNotification(context, broadcastDispatcher, pipController);
+ }
+
+ @SysUISingleton
+ @Provides
+ static PipBoundsHandler providesPipBoundsHandler(Context context) {
+ return new PipBoundsHandler(context);
+ }
+
+ @SysUISingleton
+ @Provides
+ static PipTaskOrganizer providesPipTaskOrganizer(Context context,
+ PipBoundsHandler pipBoundsHandler,
+ PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
+ Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
+ PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
+ return new PipTaskOrganizer(context, pipBoundsHandler,
+ pipSurfaceTransactionHelper, splitScreenOptional, displayController,
+ pipUiEventLogger, shellTaskOrganizer);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 2a976f546ba4..ed8da7c3d80b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents;
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
@@ -65,6 +64,7 @@ import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.Dumpable;
@@ -77,6 +77,7 @@ import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipAnimationController;
+import com.android.systemui.pip.phone.PipUtils;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.recents.IOverviewProxy;
@@ -155,7 +156,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
- private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
+ @VisibleForTesting
+ public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@Override
public void startScreenPinning(int taskId) {
@@ -624,7 +626,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
super(broadcastDispatcher);
mContext = context;
mPipOptional = pipOptional;
- mHasPipFeature = mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ mHasPipFeature = PipUtils.hasSystemFeature(mContext);
mStatusBarOptionalLazy = statusBarOptionalLazy;
mHandler = new Handler();
mNavBarControllerLazy = navBarControllerLazy;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3665c39bd9ea..af6ac223ada1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -40,12 +40,15 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.keyguard.dagger.RootView;
import com.android.systemui.DejankUtils;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import javax.inject.Inject;
@@ -66,7 +69,8 @@ public class KeyguardBouncer {
private final FalsingManager mFalsingManager;
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final Handler mHandler;
- private final BouncerExpansionCallback mExpansionCallback;
+ private final List<BouncerExpansionCallback> mExpansionCallbacks = new ArrayList<>();
+ private final AuthController mAuthController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardSecurityModel mKeyguardSecurityModel;
@@ -100,6 +104,7 @@ public class KeyguardBouncer {
ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
BouncerExpansionCallback expansionCallback,
+ AuthController authController,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardBypassController keyguardBypassController, Handler handler,
@@ -111,13 +116,15 @@ public class KeyguardBouncer {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mFalsingManager = falsingManager;
mDismissCallbackRegistry = dismissCallbackRegistry;
- mExpansionCallback = expansionCallback;
mHandler = handler;
mKeyguardStateController = keyguardStateController;
mKeyguardSecurityModel = keyguardSecurityModel;
mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mKeyguardBypassController = keyguardBypassController;
+ mExpansionCallbacks.add(expansionCallback);
+ mExpansionCallbacks.add(authController);
+ mAuthController = authController;
}
public void show(boolean resetSecuritySelection) {
@@ -188,7 +195,7 @@ public class KeyguardBouncer {
}
mCallback.onBouncerVisiblityChanged(true /* shown */);
- mExpansionCallback.onStartingToShow();
+ dispatchStartingToShow();
}
public boolean isScrimmed() {
@@ -290,6 +297,11 @@ public class KeyguardBouncer {
mIsScrimmed = false;
mFalsingManager.onBouncerHidden();
mCallback.onBouncerVisiblityChanged(false /* shown */);
+ // TODO(b/165257355): `mAuthController.onFullyHidden` should be `dispatchFullyHidden()`
+ // But, it is causing the UDFPS icon to disappear after SystemUI restarts. I guess the
+ // ExpansionCallback from StatusBarKeyguardViewManager can't handle the call to
+ // onFullyHidden after a restart.
+ mAuthController.onFullyHidden();
cancelShowRunnable();
if (mKeyguardViewController != null) {
mKeyguardViewController.cancelDismissAction();
@@ -382,12 +394,12 @@ public class KeyguardBouncer {
if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
onFullyShown();
- mExpansionCallback.onFullyShown();
+ dispatchFullyShown();
} else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
onFullyHidden();
- mExpansionCallback.onFullyHidden();
+ dispatchFullyHidden();
} else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
- mExpansionCallback.onStartingToHide();
+ dispatchStartingToHide();
if (mKeyguardViewController != null) {
mKeyguardViewController.onStartingToHide();
}
@@ -492,6 +504,30 @@ public class KeyguardBouncer {
mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
}
+ private void dispatchFullyShown() {
+ for (BouncerExpansionCallback callback : mExpansionCallbacks) {
+ callback.onFullyShown();
+ }
+ }
+
+ private void dispatchStartingToHide() {
+ for (BouncerExpansionCallback callback : mExpansionCallbacks) {
+ callback.onStartingToHide();
+ }
+ }
+
+ private void dispatchStartingToShow() {
+ for (BouncerExpansionCallback callback : mExpansionCallbacks) {
+ callback.onStartingToShow();
+ }
+ }
+
+ private void dispatchFullyHidden() {
+ for (BouncerExpansionCallback callback : mExpansionCallbacks) {
+ callback.onFullyHidden();
+ }
+ }
+
public void dump(PrintWriter pw) {
pw.println("KeyguardBouncer");
pw.println(" isShowing(): " + isShowing());
@@ -516,6 +552,7 @@ public class KeyguardBouncer {
private final ViewMediatorCallback mCallback;
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final FalsingManager mFalsingManager;
+ private final AuthController mAuthController;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardBypassController mKeyguardBypassController;
@@ -526,6 +563,7 @@ public class KeyguardBouncer {
@Inject
public Factory(Context context, ViewMediatorCallback callback,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
+ AuthController authController,
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
KeyguardBypassController keyguardBypassController, Handler handler,
@@ -535,6 +573,7 @@ public class KeyguardBouncer {
mCallback = callback;
mDismissCallbackRegistry = dismissCallbackRegistry;
mFalsingManager = falsingManager;
+ mAuthController = authController;
mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardBypassController = keyguardBypassController;
@@ -547,8 +586,9 @@ public class KeyguardBouncer {
BouncerExpansionCallback expansionCallback) {
return new KeyguardBouncer(mContext, mCallback, container,
mDismissCallbackRegistry, mFalsingManager, expansionCallback,
- mKeyguardStateController, mKeyguardUpdateMonitor, mKeyguardBypassController,
- mHandler, mKeyguardSecurityModel, mKeyguardBouncerComponentFactory);
+ mAuthController, mKeyguardStateController, mKeyguardUpdateMonitor,
+ mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
+ mKeyguardBouncerComponentFactory);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 51209d166eee..9e2e57e7047e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.navigationBars;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
@@ -803,12 +801,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
@Override
public void run() {
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
- .show(navigationBars());
- } else {
- mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
- }
+ mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
+ .show(navigationBars());
}
};
@@ -876,12 +870,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
} else {
mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
- if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
- .hide(navigationBars());
- } else {
- mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
- }
+ mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
+ .hide(navigationBars());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
index 22fa0106795a..f277b30e589d 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
@@ -17,11 +17,12 @@
package com.android.systemui.tv;
import com.android.systemui.dagger.GlobalRootComponent;
+import com.android.systemui.pip.tv.dagger.TvPipModule;
import dagger.Binds;
import dagger.Module;
-@Module()
+@Module(includes = TvPipModule.class)
interface TvSystemUIBinder {
@Binds
GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent);
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
index aa50292edbf7..71b255229c8f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
@@ -199,7 +199,7 @@ class ThresholdSensorImpl implements ThresholdSensor {
@Override
public String toString() {
- return String.format("{registered=%s, paused=%s, threshold=%s, sensor=%s}",
+ return String.format("{isLoaded=%s, registered=%s, paused=%s, threshold=%s, sensor=%s}",
isLoaded(), mRegistered, mPaused, mThreshold, mSensor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 0869cf739d02..524eca389ceb 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -20,17 +20,9 @@ import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.pip.Pip;
-import com.android.systemui.pip.PipBoundsHandler;
-import com.android.systemui.pip.PipSurfaceTransactionHelper;
-import com.android.systemui.pip.PipTaskOrganizer;
-import com.android.systemui.pip.PipUiEventLogger;
-import com.android.systemui.pip.tv.PipController;
-import com.android.systemui.pip.tv.PipNotification;
-import com.android.systemui.pip.tv.dagger.TvPipComponent;
+import com.android.systemui.pip.tv.dagger.TvPipModule;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -39,8 +31,6 @@ import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import java.util.Optional;
-
import dagger.Module;
import dagger.Provides;
@@ -49,7 +39,7 @@ import dagger.Provides;
* branches of SystemUI.
*/
// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
-@Module(includes = WMShellBaseModule.class, subcomponents = {TvPipComponent.class})
+@Module(includes = {WMShellBaseModule.class, TvPipModule.class})
public class TvWMShellModule {
@SysUISingleton
@Provides
@@ -61,17 +51,6 @@ public class TvWMShellModule {
@SysUISingleton
@Provides
- static Pip providePipController(Context context,
- BroadcastDispatcher broadcastDispatcher,
- PipBoundsHandler pipBoundsHandler,
- PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
- PipTaskOrganizer pipTaskOrganizer) {
- return new PipController(context, broadcastDispatcher, pipBoundsHandler,
- pipSurfaceTransactionHelper, pipTaskOrganizer);
- }
-
- @SysUISingleton
- @Provides
static SplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler,
@@ -79,30 +58,4 @@ public class TvWMShellModule {
return new SplitScreenController(context, displayController, systemWindows,
displayImeController, handler, transactionPool, shellTaskOrganizer);
}
-
- @SysUISingleton
- @Provides
- static PipNotification providePipNotification(Context context,
- BroadcastDispatcher broadcastDispatcher,
- PipController pipController) {
- return new PipNotification(context, broadcastDispatcher, pipController);
- }
-
- @SysUISingleton
- @Provides
- static PipBoundsHandler providesPipBoundsHandler(Context context) {
- return new PipBoundsHandler(context);
- }
-
- @SysUISingleton
- @Provides
- static PipTaskOrganizer providesPipTaskOrganizer(Context context,
- PipBoundsHandler pipBoundsHandler,
- PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
- Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
- PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
- return new PipTaskOrganizer(context, pipBoundsHandler,
- pipSurfaceTransactionHelper, splitScreenOptional, displayController,
- pipUiEventLogger, shellTaskOrganizer);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index ce125f3fdce0..a2d6ac8f8511 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -40,6 +40,7 @@ import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.pip.Pip;
+import com.android.systemui.pip.phone.PipUtils;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.tracing.ProtoTraceable;
@@ -57,7 +58,6 @@ import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Optional;
@@ -103,7 +103,6 @@ public final class WMShell extends SystemUI
ProtoTracer protoTracer) {
super(context);
mCommandQueue = commandQueue;
- mCommandQueue.addCallback(this);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mActivityManagerWrapper = activityManagerWrapper;
mDisplayImeController = displayImeController;
@@ -120,6 +119,7 @@ public final class WMShell extends SystemUI
@Override
public void start() {
+ mCommandQueue.addCallback(this);
// This is to prevent circular init problem by separating registration step out of its
// constructor. And make sure the initialization of DisplayImeController won't depend on
// specific feature anymore.
@@ -131,6 +131,9 @@ public final class WMShell extends SystemUI
@VisibleForTesting
void initPip(Pip pip) {
+ if (!PipUtils.hasSystemFeature(mContext)) {
+ return;
+ }
mCommandQueue.addCallback(new CommandQueue.Callbacks() {
@Override
public void showPictureInPictureMenu() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 88608ebde5b6..66656c5d251c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -22,6 +22,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -505,6 +506,30 @@ public class AuthControllerTest extends SysuiTestCase {
verify(mUdfpsController).onCancelAodInterrupt();
}
+ @Test
+ public void testOnFullyShown_DelegatesToUdfpsController() {
+ mAuthController.onFullyShown();
+ verify(mUdfpsController).setBouncerVisibility(eq(true));
+ }
+
+ @Test
+ public void testOnFullyHidden_DelegatesToUdfpsController() {
+ mAuthController.onFullyHidden();
+ verify(mUdfpsController).setBouncerVisibility(eq(false));
+ }
+
+ @Test
+ public void testOnStartingToShow_NeverDelegatesToUdfpsController() {
+ mAuthController.onStartingToShow();
+ verify(mUdfpsController).setBouncerVisibility(eq(true));
+ }
+
+ @Test
+ public void testOnStartingToHide_NeverDelegatesToUdfpsController() {
+ mAuthController.onStartingToHide();
+ verify(mUdfpsController, never()).setBouncerVisibility(anyBoolean());
+ }
+
// Helpers
private void showDialog(int authenticators, int biometricModality) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 87ec72fe0a01..9b9f840e5383 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.biometrics;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -151,6 +152,41 @@ public class UdfpsControllerTest extends SysuiTestCase {
}
@Test
+ public void showUdfpsOverlay_bouncerShowing() throws RemoteException {
+ // GIVEN that the bouncer is showing
+ mUdfpsController.setBouncerVisibility(/* isShowing */ true);
+ // WHEN a request to show the overlay is received
+ mOverlayController.showUdfpsOverlay();
+ mFgExecutor.runAllReady();
+ // THEN the overlay is not attached
+ verify(mWindowManager, never()).addView(eq(mUdfpsView), any());
+ }
+
+ @Test
+ public void setBouncerVisibility_overlayDetached() throws RemoteException {
+ // GIVEN that the overlay has been requested
+ mOverlayController.showUdfpsOverlay();
+ // WHEN the bouncer becomes visible
+ mUdfpsController.setBouncerVisibility(/* isShowing */ true);
+ mFgExecutor.runAllReady();
+ // THEN the overlay is detached
+ verify(mWindowManager).removeView(eq(mUdfpsView));
+ }
+
+ @Test
+ public void setBouncerVisibility_overlayAttached() throws RemoteException {
+ // GIVEN that the bouncer is visible
+ mUdfpsController.setBouncerVisibility(/* isShowing */ true);
+ // AND the overlay has been requested
+ mOverlayController.showUdfpsOverlay();
+ // WHEN the bouncer is closed
+ mUdfpsController.setBouncerVisibility(/* isShowing */ false);
+ mFgExecutor.runAllReady();
+ // THEN the overlay is attached
+ verify(mWindowManager).addView(eq(mUdfpsView), any());
+ }
+
+ @Test
public void fingerDown() throws RemoteException {
// Configure UdfpsView to accept the ACTION_DOWN event
when(mUdfpsView.isScrimShowing()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
index 1dc415048f74..2e8e3ed664b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
@@ -122,4 +122,8 @@ public class WakefulnessLifecycleTest extends SysuiTestCase {
mWakefulness.dump(null, new PrintWriter(new ByteArrayOutputStream()), new String[0]);
}
-} \ No newline at end of file
+ @Test(expected = NullPointerException.class)
+ public void throwNPEOnNullObserver() {
+ mWakefulness.addObserver(null);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java
new file mode 100644
index 000000000000..b04349521205
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.phone;
+
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSurfaceTransactionHelper;
+import com.android.systemui.pip.PipTaskOrganizer;
+import com.android.systemui.pip.PipUiEventLogger;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.FloatingContentCoordinator;
+import com.android.wm.shell.common.DisplayController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link PipController}
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class PipControllerTest extends SysuiTestCase {
+ private PipController mPipController;
+ private TestableContext mSpiedContext;
+
+ @Mock private ActivityManagerWrapper mMockActivityManagerWrapper;
+ @Mock private BroadcastDispatcher mMockBroadcastDispatcher;
+ @Mock private ConfigurationController mMockConfigurationController;
+ @Mock private DeviceConfigProxy mMockDeviceConfigProxy;
+ @Mock private DisplayController mMockdDisplayController;
+ @Mock private FloatingContentCoordinator mMockFloatingContentCoordinator;
+ @Mock private PackageManager mPackageManager;
+ @Mock private PipBoundsHandler mMockPipBoundsHandler;
+ @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
+ @Mock private PipTaskOrganizer mMockPipTaskOrganizer;
+ @Mock private PipUiEventLogger mPipUiEventLogger;
+ @Mock private SysUiState mMockSysUiState;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+
+ mSpiedContext = spy(mContext);
+
+ when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
+ when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mPipController = new PipController(mSpiedContext, mMockBroadcastDispatcher,
+ mMockConfigurationController, mMockDeviceConfigProxy, mMockdDisplayController,
+ mMockFloatingContentCoordinator, mMockSysUiState, mMockPipBoundsHandler,
+ mMockPipSurfaceTransactionHelper, mMockPipTaskOrganizer, mPipUiEventLogger);
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotRegisterTaskStackListener() {
+ verify(mMockActivityManagerWrapper, never()).registerTaskStackListener(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotRegisterPipTransitionCallback() {
+ verify(mMockPipTaskOrganizer, never()).registerPipTransitionCallback(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotAddDisplayChangingController() {
+ verify(mMockdDisplayController, never()).addDisplayChangingController(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotAddDisplayWindowListener() {
+ verify(mMockdDisplayController, never()).addDisplayWindowListener(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotAddCallback() {
+ verify(mMockConfigurationController, never()).addCallback(any());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java
new file mode 100644
index 000000000000..b1a7df83fa9f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.phone;
+
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSurfaceTransactionHelper;
+import com.android.systemui.pip.PipTaskOrganizer;
+import com.android.systemui.pip.PipUiEventLogger;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+/**
+ * Unit tests for {@link PipTaskOrganizer}
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class PipTaskOrganizerTest extends SysuiTestCase {
+ private PipTaskOrganizer mSpiedPipTaskOrganizer;
+ private TestableContext mSpiedContext;
+
+ @Mock private DisplayController mMockdDisplayController;
+ @Mock private PackageManager mPackageManager;
+ @Mock private PipBoundsHandler mMockPipBoundsHandler;
+ @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
+ @Mock private PipUiEventLogger mMockPipUiEventLogger;
+ @Mock private Optional<SplitScreen> mMockOptionalSplitScreen;
+ @Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+
+ mSpiedContext = spy(mContext);
+
+ when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
+ when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mSpiedContext, mMockPipBoundsHandler,
+ mMockPipSurfaceTransactionHelper, mMockOptionalSplitScreen, mMockdDisplayController,
+ mMockPipUiEventLogger, mMockShellTaskOrganizer));
+ }
+
+ @Test
+ public void testNonPipDevice_shellTaskOrganizer_shouldNotAddListener() {
+ verify(mMockShellTaskOrganizer, never()).addListener(any(), anyInt());
+ }
+
+ @Test
+ public void testNonPipDevice_displayController_shouldNotAddDisplayWindowListener() {
+ verify(mMockdDisplayController, never()).addDisplayWindowListener(any());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
new file mode 100644
index 000000000000..727f91c589df
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.recents;
+
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.pip.Pip;
+import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+import dagger.Lazy;
+
+/**
+ * Unit tests for {@link com.android.systemui.recents.OverviewProxyService}
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class OverviewProxyServiceTest extends SysuiTestCase {
+ private OverviewProxyService mSpiedOverviewProxyService;
+ private TestableContext mSpiedContext;
+
+ @Mock private BroadcastDispatcher mMockBroadcastDispatcher;
+ @Mock private CommandQueue mMockCommandQueue;
+ @Mock private Lazy<NavigationBarController> mMockNavBarControllerLazy;
+ @Mock private IPinnedStackAnimationListener mMockPinnedStackAnimationListener;
+ @Mock private NavigationModeController mMockNavModeController;
+ @Mock private NotificationShadeWindowController mMockStatusBarWinController;
+ @Mock private Optional<Pip> mMockPipOptional;
+ @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
+ @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
+ @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
+ @Mock private PackageManager mPackageManager;
+ @Mock private SysUiState mMockSysUiState;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+
+ mSpiedContext = spy(mContext);
+
+ when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
+ when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mSpiedOverviewProxyService = spy(new OverviewProxyService(mSpiedContext, mMockCommandQueue,
+ mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController,
+ mMockSysUiState, mMockPipOptional, mMockSplitScreenOptional,
+ mMockStatusBarOptionalLazy, mMockOneHandedOptional,
+ mMockBroadcastDispatcher));
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotNotifySwipeToHomeFinished() throws RemoteException {
+ mSpiedOverviewProxyService.mSysUiProxy.notifySwipeToHomeFinished();
+
+ verify(mMockPipOptional, never()).ifPresent(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotSetPinnedStackAnimationListener() throws RemoteException {
+ mSpiedOverviewProxyService.mSysUiProxy.setPinnedStackAnimationListener(
+ mMockPinnedStackAnimationListener);
+
+ verify(mMockPipOptional, never()).ifPresent(any());
+ }
+
+ @Test
+ public void testNonPipDevice_shouldNotSetShelfHeight() throws RemoteException {
+ mSpiedOverviewProxyService.mSysUiProxy.setShelfHeight(true /* visible */,
+ 100 /* shelfHeight */);
+
+ verify(mMockPipOptional, never()).ifPresent(any());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 1b05ad7f8b5b..4fb45ec18178 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -50,6 +50,7 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.FalsingManager;
@@ -78,6 +79,8 @@ public class KeyguardBouncerTest extends SysuiTestCase {
@Mock
private DismissCallbackRegistry mDismissCallbackRegistry;
@Mock
+ private AuthController mAuthController;
+ @Mock
private KeyguardHostViewController mKeyguardHostViewController;
@Mock
private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback;
@@ -128,7 +131,7 @@ public class KeyguardBouncerTest extends SysuiTestCase {
final ViewGroup container = new FrameLayout(getContext());
mBouncer = new KeyguardBouncer.Factory(getContext(), mViewMediatorCallback,
- mDismissCallbackRegistry, mFalsingManager,
+ mDismissCallbackRegistry, mFalsingManager, mAuthController,
mKeyguardStateController, mKeyguardUpdateMonitor,
mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
mKeyguardBouncerComponentFactory)
@@ -207,6 +210,12 @@ public class KeyguardBouncerTest extends SysuiTestCase {
}
@Test
+ public void testShow_notifiesAuthControllerStartingToShow() {
+ mBouncer.show(/* resetSecuritySelection */ false);
+ verify(mAuthController).onStartingToShow();
+ }
+
+ @Test
public void testSetExpansion_notifiesFalsingManager() {
mBouncer.ensureView();
mBouncer.setExpansion(0.5f);
@@ -237,6 +246,38 @@ public class KeyguardBouncerTest extends SysuiTestCase {
}
@Test
+ public void testSetExpansion_notifiesAuthControllerFullyShown() {
+ mBouncer.ensureView();
+ mBouncer.setExpansion(0.1f);
+ mBouncer.setExpansion(0f);
+ verify(mAuthController).onFullyShown();
+ }
+
+ @Test
+ public void testSetExpansion_notifiesAuthControllerStartingToHide() {
+ mBouncer.ensureView();
+ mBouncer.setExpansion(0f);
+ mBouncer.setExpansion(0.1f);
+ verify(mAuthController).onStartingToHide();
+ }
+
+ @Test
+ public void testSetExpansion_notifiesAuthControllerFullyHidden() {
+ mBouncer.ensureView();
+ mBouncer.setExpansion(0.9f);
+ mBouncer.setExpansion(1f);
+ verify(mAuthController).onFullyHidden();
+ }
+
+ @Test
+ public void testSetExpansion_negativeAuthControllerStartingToShow() {
+ mBouncer.ensureView();
+ mBouncer.setExpansion(1f);
+ mBouncer.setExpansion(0.9f);
+ verify(mAuthController, never()).onStartingToShow();
+ }
+
+ @Test
public void testHide_notifiesFalsingManager() {
mBouncer.hide(false);
verify(mFalsingManager).onBouncerHidden();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index ef4d1078b8b9..280423fca202 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -16,12 +16,17 @@
package com.android.systemui.wmshell;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.pm.PackageManager;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableContext;
import androidx.test.runner.AndroidJUnit4;
@@ -68,6 +73,7 @@ public class WMShellTest extends SysuiTestCase {
@Mock OneHanded mOneHanded;
@Mock ShellTaskOrganizer mTaskOrganizer;
@Mock ProtoTracer mProtoTracer;
+ @Mock PackageManager mMockPackageManager;
@Before
public void setUp() {
@@ -89,8 +95,23 @@ public class WMShellTest extends SysuiTestCase {
public void initPip_registersCommandQueueCallback() {
mWMShell.initPip(mPip);
- // Once for the shell, once for pip
- verify(mCommandQueue, times(2)).addCallback(any(CommandQueue.Callbacks.class));
+ verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
+ }
+
+ @Test
+ public void nonPipDevice_shouldNotInitPip() {
+ TestableContext spiedContext = spy(mContext);
+ when(mMockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
+ when(spiedContext.getPackageManager()).thenReturn(mMockPackageManager);
+
+ final WMShell nonPipWMShell = new WMShell(spiedContext, mCommandQueue,
+ mKeyguardUpdateMonitor,
+ mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
+ mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
+ Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
+ nonPipWMShell.initPip(mPip);
+
+ verify(mCommandQueue, never()).addCallback(any());
}
@Test
@@ -108,8 +129,7 @@ public class WMShellTest extends SysuiTestCase {
mWMShell.initOneHanded(mOneHanded);
verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
- // Once for the shell, once for the one handed mode
- verify(mCommandQueue, times(2)).addCallback(any(CommandQueue.Callbacks.class));
+ verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
verify(mNavigationModeController).addListener(
any(NavigationModeController.ModeChangedListener.class));
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index ee03b150b519..9495fb5fdc77 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -707,12 +707,12 @@ public class AccessibilityWindowManager {
case WindowManager.LayoutParams.TYPE_PHONE:
case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
case WindowManager.LayoutParams.TYPE_TOAST:
- case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
+ case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
return AccessibilityWindowInfo.TYPE_APPLICATION;
}
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD: {
return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 20f3231de200..bfe04e628f81 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2609,12 +2609,12 @@ public final class ActiveServices {
private int getAllowMode(Intent service, @Nullable String callingPackage) {
if (callingPackage == null || service.getComponent() == null) {
- return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+ return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL;
}
if (callingPackage.equals(service.getComponent().getPackageName())) {
- return ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE;
+ return ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL;
} else {
- return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+ return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b1b4018036c0..2de3e525d2da 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5753,11 +5753,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public void positionTaskInStack(int taskId, int stackId, int position) {
- mActivityTaskManager.positionTaskInStack(taskId, stackId, position);
- }
-
- @Override
public List<RootTaskInfo> getAllRootTaskInfos() {
return mActivityTaskManager.getAllRootTaskInfos();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9ce8b11a7351..11197287114c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2582,8 +2582,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
switch (op) {
case "move-task":
return runStackMoveTask(pw);
- case "positiontask":
- return runStackPositionTask(pw);
case "list":
return runStackList(pw);
case "info":
@@ -2656,18 +2654,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
- int runStackPositionTask(PrintWriter pw) throws RemoteException {
- String taskIdStr = getNextArgRequired();
- int taskId = Integer.parseInt(taskIdStr);
- String stackIdStr = getNextArgRequired();
- int stackId = Integer.parseInt(stackIdStr);
- String positionStr = getNextArgRequired();
- int position = Integer.parseInt(positionStr);
-
- mTaskInterface.positionTaskInStack(taskId, stackId, position);
- return 0;
- }
-
int runStackList(PrintWriter pw) throws RemoteException {
List<RootTaskInfo> tasks = mTaskInterface.getAllRootTaskInfos();
for (RootTaskInfo info : tasks) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f42753287e35..808a6993af1a 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -276,15 +276,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
private void awaitCompletion() {
- synchronized (mLock) {
- final CountDownLatch latch = new CountDownLatch(1);
- mHandler.post(() -> {
- latch.countDown();
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- }
+ final CountDownLatch latch = new CountDownLatch(1);
+ mHandler.post(() -> {
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
}
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index eb60573e6f17..3dfbcc71dd3c 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -23,10 +23,11 @@ import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM;
import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
import static android.app.ActivityManager.USER_OP_IS_CURRENT;
import static android.app.ActivityManager.USER_OP_SUCCESS;
-import static android.app.ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE;
+import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL;
+import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
-import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
@@ -1911,11 +1912,12 @@ class UserController implements Handler.Callback {
callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
// If the caller does not have either permission, they are always doomed.
allow = false;
- } else if (allowMode == ALLOW_NON_FULL) {
+ } else if (allowMode == ALLOW_NON_FULL
+ || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL) {
// We are blanket allowing non-full access, you lucky caller!
allow = true;
- } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE
- || allowMode == ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) {
+ } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE_OR_FULL
+ || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL) {
// We may or may not allow this depending on whether the two users are
// in the same profile.
allow = isSameProfileGroup;
@@ -1942,12 +1944,15 @@ class UserController implements Handler.Callback {
builder.append("; this requires ");
builder.append(INTERACT_ACROSS_USERS_FULL);
if (allowMode != ALLOW_FULL_ONLY) {
- if (allowMode == ALLOW_NON_FULL || isSameProfileGroup) {
+ if (allowMode == ALLOW_NON_FULL
+ || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL
+ || isSameProfileGroup) {
builder.append(" or ");
builder.append(INTERACT_ACROSS_USERS);
}
if (isSameProfileGroup
- && allowMode == ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) {
+ && (allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL
+ || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL)) {
builder.append(" or ");
builder.append(INTERACT_ACROSS_PROFILES);
}
@@ -1974,7 +1979,8 @@ class UserController implements Handler.Callback {
private boolean canInteractWithAcrossProfilesPermission(
int allowMode, boolean isSameProfileGroup, int callingPid, int callingUid,
String callingPackage) {
- if (allowMode != ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) {
+ if (allowMode != ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL
+ && allowMode != ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL) {
return false;
}
if (!isSameProfileGroup) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a80111c2f781..6099e52e54e9 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -19,6 +19,7 @@ package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL;
import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP;
import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
@@ -36,6 +37,7 @@ import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
+import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
@@ -129,6 +131,7 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.KeyValueListParser;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -162,6 +165,7 @@ import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemServiceManager;
+import com.android.server.am.ActivityManagerService;
import com.android.server.pm.PackageList;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -1794,9 +1798,9 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
}
-
- mHistoricalRegistry.clearHistory(uid, packageName);
}
+
+ mHistoricalRegistry.clearHistory(uid, packageName);
}
public void uidRemoved(int uid) {
@@ -2199,8 +2203,11 @@ public class AppOpsService extends IAppOpsService.Stub {
+ " by uid " + Binder.getCallingUid());
}
+ int userId = UserHandle.getUserId(uid);
+
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
verifyIncomingOp(code);
+ verifyIncomingUser(userId);
code = AppOpsManager.opToSwitch(code);
if (permissionPolicyCallback == null) {
@@ -2245,6 +2252,11 @@ public class AppOpsService extends IAppOpsService.Stub {
scheduleWriteLocked();
}
uidState.evalForegroundOps(mOpModeWatchers);
+
+ if (code == OP_INTERACT_ACROSS_PROFILES) {
+ // Invalidate package info cache as the visibility of packages might have changed
+ PackageManager.invalidatePackageInfoCache();
+ }
}
notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback);
@@ -2450,8 +2462,12 @@ public class AppOpsService extends IAppOpsService.Stub {
private void setMode(int code, int uid, @NonNull String packageName, int mode,
@Nullable IAppOpsCallback permissionPolicyCallback) {
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
+
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
ArraySet<ModeCallback> repCbs = null;
code = AppOpsManager.opToSwitch(code);
@@ -2713,6 +2729,9 @@ public class AppOpsService extends IAppOpsService.Stub {
if (changed) {
scheduleFastWriteLocked();
+
+ // Invalidate package info cache as the visibility of packages might have changed
+ PackageManager.invalidatePackageInfoCache();
}
}
if (callbacks != null) {
@@ -2871,8 +2890,11 @@ public class AppOpsService extends IAppOpsService.Stub {
private int checkOperationImpl(int code, int uid, String packageName,
boolean raw) {
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
@@ -2991,10 +3013,15 @@ public class AppOpsService extends IAppOpsService.Stub {
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage) {
+ int proxiedUserId = UserHandle.getUserId(proxiedUid);
+ int proxyUserId = UserHandle.getUserId(proxyUid);
+
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
- verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid));
- verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid));
+ verifyIncomingUser(proxiedUserId);
+ verifyIncomingUser(proxyUserId);
+ verifyIncomingPackage(proxiedPackageName, proxiedUserId);
+ verifyIncomingPackage(proxyPackageName, proxyUserId);
String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
if (resolveProxyPackageName == null) {
@@ -3044,9 +3071,12 @@ public class AppOpsService extends IAppOpsService.Stub {
private int noteOperationImpl(int code, int uid, @Nullable String packageName,
@Nullable String attributionTag, boolean shouldCollectAsyncNotedOp,
@Nullable String message, boolean shouldCollectMessage) {
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingUid(uid);
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
@@ -3423,9 +3453,12 @@ public class AppOpsService extends IAppOpsService.Stub {
public int startOperation(IBinder clientId, int code, int uid, String packageName,
String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
String message, boolean shouldCollectMessage) {
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingUid(uid);
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
@@ -3517,9 +3550,12 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public void finishOperation(IBinder clientId, int code, int uid, String packageName,
String attributionTag) {
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingUid(uid);
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
@@ -3748,6 +3784,33 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ private void verifyIncomingUser(@UserIdInt int userId) {
+ int callingUid = Binder.getCallingUid();
+ int callingUserId = UserHandle.getUserId(callingUid);
+ int callingPid = Binder.getCallingPid();
+
+ if (callingUserId != userId) {
+ // Prevent endless loop between when checking appops inside of handleIncomingUser
+ if (Binder.getCallingPid() == ActivityManagerService.MY_PID) {
+ return;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ try {
+ LocalServices.getService(ActivityManagerInternal.class).handleIncomingUser(
+ callingPid, callingUid, userId, /* allowAll */ false,
+ ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL, "appop operation", null);
+ } catch (Exception e) {
+ EventLog.writeEvent(0x534e4554, "153996875", "appop", userId);
+
+ throw e;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
private @Nullable UidState getUidStateLocked(int uid, boolean edit) {
UidState uidState = mUidStates.get(uid);
if (uidState == null) {
@@ -5827,8 +5890,11 @@ public class AppOpsService extends IAppOpsService.Stub {
return false;
}
}
+ int userId = UserHandle.getUserId(uid);
+
verifyIncomingOp(code);
- verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
+ verifyIncomingUser(userId);
+ verifyIncomingPackage(packageName, userId);
final String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index 84de25c06ebf..a3e1b7a7e5c5 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -7,6 +7,9 @@
"name": "CtsAppOps2TestCases"
},
{
+ "name": "CtsAppOpHostTestCases"
+ },
+ {
"name": "FrameworksServicesTests",
"options": [
{
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 0d824334d873..23e5a43a359f 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -18,6 +18,7 @@ package com.android.server.display;
import android.os.Environment;
import android.util.Slog;
+import android.view.DisplayAddress;
import com.android.server.display.config.DisplayConfiguration;
import com.android.server.display.config.NitsMap;
@@ -31,6 +32,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
import java.util.List;
import javax.xml.datatype.DatatypeConfigurationException;
@@ -45,7 +47,11 @@ public class DisplayDeviceConfig {
private static final String ETC_DIR = "etc";
private static final String DISPLAY_CONFIG_DIR = "displayconfig";
- private static final String CONFIG_FILE_FORMAT = "display_%d.xml";
+ private static final String CONFIG_FILE_FORMAT = "display_%s.xml";
+ private static final String PORT_SUFFIX_FORMAT = "port_%d";
+ private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d";
+ private static final String NO_SUFFIX_FORMAT = "%d";
+ private static final long STABLE_FLAG = 1L << 62;
private float[] mNits;
private float[] mBrightness;
@@ -55,17 +61,43 @@ public class DisplayDeviceConfig {
/**
* Creates an instance for the specified display.
- *
+ * Tries to find a file with identifier in the following priority order:
+ * <ol>
+ * <li>physicalDisplayId</li>
+ * <li>physicalDisplayId without a stable flag (old system)</li>
+ * <li>portId</li>
+ * </ol>
* @param physicalDisplayId The display ID for which to load the configuration.
* @return A configuration instance for the specified display.
*/
public static DisplayDeviceConfig create(long physicalDisplayId) {
- final DisplayDeviceConfig config = new DisplayDeviceConfig();
- final String filename = String.format(CONFIG_FILE_FORMAT, physicalDisplayId);
+ DisplayDeviceConfig config;
+
+ // Create config using filename from physical ID (including "stable" bit).
+ config = getConfigFromSuffix(STABLE_ID_SUFFIX_FORMAT, physicalDisplayId);
+ if (config != null) {
+ return config;
+ }
+
+ // Create config using filename from physical ID (excluding "stable" bit).
+ final long withoutStableFlag = physicalDisplayId & ~STABLE_FLAG;
+ config = getConfigFromSuffix(NO_SUFFIX_FORMAT, withoutStableFlag);
+ if (config != null) {
+ return config;
+ }
+
+ // Create config using filename from port ID.
+ final DisplayAddress.Physical physicalAddress =
+ DisplayAddress.fromPhysicalDisplayId(physicalDisplayId);
+ int port = physicalAddress.getPort();
+ config = getConfigFromSuffix(PORT_SUFFIX_FORMAT, port);
+ if (config != null) {
+ return config;
+ }
+
+ // None of these files exist.
+ return null;
- config.initFromFile(Environment.buildPath(
- Environment.getProductDirectory(), ETC_DIR, DISPLAY_CONFIG_DIR, filename));
- return config;
}
/**
@@ -86,6 +118,30 @@ public class DisplayDeviceConfig {
return mBrightness;
}
+ @Override
+ public String toString() {
+ String str = "DisplayDeviceConfig{"
+ + "mBrightness=" + Arrays.toString(mBrightness)
+ + ", mNits=" + Arrays.toString(mNits)
+ + "}";
+ return str;
+ }
+
+ private static DisplayDeviceConfig getConfigFromSuffix(String suffixFormat, long idNumber) {
+
+ final String suffix = String.format(suffixFormat, idNumber);
+ final String filename = String.format(CONFIG_FILE_FORMAT, suffix);
+ final File filePath = Environment.buildPath(
+ Environment.getProductDirectory(), ETC_DIR, DISPLAY_CONFIG_DIR, filename);
+
+ if (filePath.exists()) {
+ final DisplayDeviceConfig config = new DisplayDeviceConfig();
+ config.initFromFile(filePath);
+ return config;
+ }
+ return null;
+ }
+
private void initFromFile(File configFile) {
if (!configFile.exists()) {
// Display configuration files aren't required to exist.
@@ -121,13 +177,13 @@ public class DisplayDeviceConfig {
if (i > 0) {
if (nits[i] < nits[i - 1]) {
Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest "
- + " of configuration. Nits: " + nits[i] + " < " + nits[i - 1]);
+ + " of configuration. Nits: " + nits[i] + " < " + nits[i - 1]);
return;
}
if (backlight[i] < backlight[i - 1]) {
Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest "
- + " of configuration. Value: " + backlight[i] + " < "
+ + " of configuration. Value: " + backlight[i] + " < "
+ backlight[i - 1]);
return;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 4a12ee71adbe..97c4cf531a53 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1179,6 +1179,15 @@ public final class DisplayManagerService extends SystemService {
return mWideColorSpace.getId();
}
+ void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
+ mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
+ }
+
+
+ boolean shouldAlwaysRespectAppRequestedModeInternal() {
+ return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode();
+ }
+
private void setBrightnessConfigurationForUserInternal(
@Nullable BrightnessConfiguration c, @UserIdInt int userId,
@Nullable String packageName) {
@@ -2463,6 +2472,32 @@ public final class DisplayManagerService extends SystemService {
}
}
+ @Override // Binder call
+ public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+ "Permission required to override display mode requests.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setShouldAlwaysRespectAppRequestedModeInternal(enabled);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public boolean shouldAlwaysRespectAppRequestedMode() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+ "Permission required to override display mode requests.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return shouldAlwaysRespectAppRequestedModeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean validatePackageName(int uid, String packageName) {
if (packageName != null) {
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index b1c91a690d7f..4f5a0faee8dd 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -56,8 +56,8 @@ import java.util.List;
import java.util.Objects;
/**
- * The DisplayModeDirector is responsible for determining what modes are allowed to be
- * automatically picked by the system based on system-wide and display-specific configuration.
+ * The DisplayModeDirector is responsible for determining what modes are allowed to be automatically
+ * picked by the system based on system-wide and display-specific configuration.
*/
public class DisplayModeDirector {
private static final String TAG = "DisplayModeDirector";
@@ -97,17 +97,20 @@ public class DisplayModeDirector {
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
+ private boolean mAlwaysRespectAppRequest;
+
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
mContext = context;
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
mVotesByDisplay = new SparseArray<>();
mSupportedModesByDisplay = new SparseArray<>();
- mDefaultModeByDisplay = new SparseArray<>();
+ mDefaultModeByDisplay = new SparseArray<>();
mAppRequestObserver = new AppRequestObserver();
mSettingsObserver = new SettingsObserver(context, handler);
mDisplayObserver = new DisplayObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler);
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
+ mAlwaysRespectAppRequest = false;
}
/**
@@ -127,7 +130,6 @@ public class DisplayModeDirector {
// notify them to pick up our newly initialized state.
notifyDesiredDisplayModeSpecsChangedLocked();
}
-
}
@NonNull
@@ -173,9 +175,14 @@ public class DisplayModeDirector {
// VoteSummary is returned as an output param to cut down a bit on the number of temporary
// objects.
private void summarizeVotes(
- SparseArray<Vote> votes, int lowestConsideredPriority, /*out*/ VoteSummary summary) {
+ SparseArray<Vote> votes,
+ int lowestConsideredPriority,
+ int highestConsideredPriority,
+ /*out*/ VoteSummary summary) {
summary.reset();
- for (int priority = Vote.MAX_PRIORITY; priority >= lowestConsideredPriority; priority--) {
+ for (int priority = highestConsideredPriority;
+ priority >= lowestConsideredPriority;
+ priority--) {
Vote vote = votes.get(priority);
if (vote == null) {
continue;
@@ -217,8 +224,16 @@ public class DisplayModeDirector {
int[] availableModes = new int[]{defaultMode.getModeId()};
VoteSummary primarySummary = new VoteSummary();
int lowestConsideredPriority = Vote.MIN_PRIORITY;
- while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
- summarizeVotes(votes, lowestConsideredPriority, primarySummary);
+ int highestConsideredPriority = Vote.MAX_PRIORITY;
+
+ if (mAlwaysRespectAppRequest) {
+ lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_REFRESH_RATE;
+ highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE;
+ }
+
+ while (lowestConsideredPriority <= highestConsideredPriority) {
+ summarizeVotes(
+ votes, lowestConsideredPriority, highestConsideredPriority, primarySummary);
// If we don't have anything specifying the width / height of the display, just use
// the default width and height. We don't want these switching out from underneath
@@ -261,7 +276,10 @@ public class DisplayModeDirector {
VoteSummary appRequestSummary = new VoteSummary();
summarizeVotes(
- votes, Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, appRequestSummary);
+ votes,
+ Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF,
+ Vote.MAX_PRIORITY,
+ appRequestSummary);
appRequestSummary.minRefreshRate =
Math.min(appRequestSummary.minRefreshRate, primarySummary.minRefreshRate);
appRequestSummary.maxRefreshRate =
@@ -338,8 +356,7 @@ public class DisplayModeDirector {
}
/**
- * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate
- * ranges.
+ * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate ranges.
*/
public void setDesiredDisplayModeSpecsListener(
@Nullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener) {
@@ -349,6 +366,26 @@ public class DisplayModeDirector {
}
/**
+ * When enabled the app requested display mode is always selected and all
+ * other votes will be ignored. This is used for testing purposes.
+ */
+ public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
+ synchronized (mLock) {
+ mAlwaysRespectAppRequest = enabled;
+ }
+ }
+
+ /**
+ * Returns whether we are running in a mode which always selects the app requested display mode
+ * and ignores user settings and policies for low brightness, low battery etc.
+ */
+ public boolean shouldAlwaysRespectAppRequestedMode() {
+ synchronized (mLock) {
+ return mAlwaysRespectAppRequest;
+ }
+ }
+
+ /**
* Print the object's state and debug information into the given stream.
*
* @param pw The stream to dump information to.
@@ -380,6 +417,7 @@ public class DisplayModeDirector {
pw.println(" " + Vote.priorityToString(p) + " -> " + vote);
}
}
+ pw.println(" mAlwaysRespectAppRequest: " + mAlwaysRespectAppRequest);
mSettingsObserver.dumpLocked(pw);
mAppRequestObserver.dumpLocked(pw);
mBrightnessObserver.dumpLocked(pw);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 0be428bdba47..507a265f0203 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -391,11 +391,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
Spline sysToNits = null;
// Load the mapping from nits to HAL brightness range (display-device-config.xml)
- DisplayDeviceConfig config = DisplayDeviceConfig.create(mPhysicalDisplayId);
- mDisplayDeviceConfig = config;
- if (config == null) {
+ mDisplayDeviceConfig = DisplayDeviceConfig.create(mPhysicalDisplayId);
+ if (mDisplayDeviceConfig == null) {
return;
}
+
final float[] halNits = mDisplayDeviceConfig.getNits();
final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
if (halNits == null || halBrightness == null) {
@@ -942,7 +942,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
for (int i = 0; i < mSupportedModes.size(); i++) {
pw.println(" " + mSupportedModes.valueAt(i));
}
- pw.print("mSupportedColorModes=" + mSupportedColorModes.toString());
+ pw.println("mSupportedColorModes=" + mSupportedColorModes.toString());
+ pw.print("mDisplayDeviceConfig=" + mDisplayDeviceConfig);
}
private int findDisplayConfigIdLocked(int modeId, int configGroup) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
new file mode 100644
index 000000000000..2878a94fb860
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
@@ -0,0 +1,192 @@
+/*
+ * 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.hdmi;
+
+import android.stats.hdmi.HdmiStatsEnums;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+class HdmiCecAtomWriter {
+
+ private static final int FEATURE_ABORT_OPCODE_UNKNOWN = 0x100;
+ private static final int ERROR_CODE_UNKNOWN = -1;
+
+ /**
+ * Writes a HdmiCecMessageReported atom representing an HDMI CEC message.
+ * Should only be directly used for sent messages; for received messages,
+ * use the overloaded version with the errorCode argument omitted.
+ *
+ * @param message The HDMI CEC message
+ * @param direction Whether the message is incoming, outgoing, or neither
+ * @param errorCode The error code from the final attempt to send the message
+ */
+ public void messageReported(HdmiCecMessage message, int direction, int errorCode) {
+ MessageReportedGenericArgs genericArgs = createMessageReportedGenericArgs(
+ message, direction, errorCode);
+ MessageReportedSpecialArgs specialArgs = createMessageReportedSpecialArgs(message);
+ messageReportedBase(genericArgs, specialArgs);
+ }
+
+ /**
+ * Version of messageReported for received messages, where no error code is present.
+ *
+ * @param message The HDMI CEC message
+ * @param direction Whether the message is incoming, outgoing, or neither
+ */
+ public void messageReported(HdmiCecMessage message, int direction) {
+ messageReported(message, direction, ERROR_CODE_UNKNOWN);
+ }
+
+ /**
+ * Constructs the generic arguments for logging a HDMI CEC message.
+ *
+ * @param message The HDMI CEC message
+ * @param direction Whether the message is incoming, outgoing, or neither
+ * @param errorCode The error code of the message if it's outgoing;
+ * otherwise, ERROR_CODE_UNKNOWN
+ */
+ private MessageReportedGenericArgs createMessageReportedGenericArgs(
+ HdmiCecMessage message, int direction, int errorCode) {
+ int sendMessageResult = errorCode == ERROR_CODE_UNKNOWN
+ ? HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN
+ : errorCode + 10;
+ return new MessageReportedGenericArgs(direction, message.getSource(),
+ message.getDestination(), message.getOpcode(), sendMessageResult);
+ }
+
+ /**
+ * Constructs the special arguments for logging an HDMI CEC message.
+ *
+ * @param message The HDMI CEC message to log
+ * @return An object containing the special arguments for the message
+ */
+ private MessageReportedSpecialArgs createMessageReportedSpecialArgs(HdmiCecMessage message) {
+ // Special arguments depend on message opcode
+ switch (message.getOpcode()) {
+ case Constants.MESSAGE_USER_CONTROL_PRESSED:
+ return createUserControlPressedSpecialArgs(message);
+ case Constants.MESSAGE_FEATURE_ABORT:
+ return createFeatureAbortSpecialArgs(message);
+ default:
+ return new MessageReportedSpecialArgs();
+ }
+ }
+
+ /**
+ * Constructs the special arguments for a <User Control Pressed> message.
+ *
+ * @param message The HDMI CEC message to log
+ */
+ private MessageReportedSpecialArgs createUserControlPressedSpecialArgs(
+ HdmiCecMessage message) {
+ MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs();
+
+ int keycode = message.getParams()[0];
+ if (keycode >= 0x1E && keycode <= 0x29) {
+ specialArgs.mUserControlPressedCommand = HdmiStatsEnums.NUMBER;
+ } else {
+ specialArgs.mUserControlPressedCommand = keycode + 0x100;
+ }
+
+ return specialArgs;
+ }
+
+ /**
+ * Constructs method for constructing the special arguments for a <Feature Abort> message.
+ *
+ * @param message The HDMI CEC message to log
+ */
+ private MessageReportedSpecialArgs createFeatureAbortSpecialArgs(HdmiCecMessage message) {
+ MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs();
+
+ specialArgs.mFeatureAbortOpcode = message.getParams()[0] & 0xFF; // Unsigned byte
+ specialArgs.mFeatureAbortReason = message.getParams()[1] + 10;
+
+ return specialArgs;
+ }
+
+ /**
+ * Writes a HdmiCecMessageReported atom.
+ *
+ * @param genericArgs Generic arguments; shared by all HdmiCecMessageReported atoms
+ * @param specialArgs Special arguments; depends on the opcode of the message
+ */
+ private void messageReportedBase(MessageReportedGenericArgs genericArgs,
+ MessageReportedSpecialArgs specialArgs) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED,
+ 0, // Placeholder field
+ genericArgs.mDirection,
+ genericArgs.mInitiatorLogicalAddress,
+ genericArgs.mDestinationLogicalAddress,
+ genericArgs.mOpcode,
+ genericArgs.mSendMessageResult,
+ specialArgs.mUserControlPressedCommand,
+ specialArgs.mFeatureAbortOpcode,
+ specialArgs.mFeatureAbortReason);
+ }
+
+
+ /**
+ * Writes a HdmiCecActiveSourceChanged atom representing a change in the active source.
+ *
+ * @param logicalAddress The Logical Address of the new active source
+ * @param physicalAddress The Physical Address of the new active source
+ * @param relationshipToActiveSource The relationship between this device and the active source
+ */
+ public void activeSourceChanged(int logicalAddress, int physicalAddress,
+ @Constants.PathRelationship int relationshipToActiveSource) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.HDMI_CEC_ACTIVE_SOURCE_CHANGED,
+ logicalAddress,
+ physicalAddress,
+ relationshipToActiveSource
+ );
+ }
+
+ /**
+ * Contains the required arguments for creating any HdmiCecMessageReported atom
+ */
+ private class MessageReportedGenericArgs {
+ final int mDirection;
+ final int mInitiatorLogicalAddress;
+ final int mDestinationLogicalAddress;
+ final int mOpcode;
+ final int mSendMessageResult;
+
+ MessageReportedGenericArgs(int direction, int initiatorLogicalAddress,
+ int destinationLogicalAddress, int opcode, int sendMessageResult) {
+ this.mDirection = direction;
+ this.mInitiatorLogicalAddress = initiatorLogicalAddress;
+ this.mDestinationLogicalAddress = destinationLogicalAddress;
+ this.mOpcode = opcode;
+ this.mSendMessageResult = sendMessageResult;
+ }
+ }
+
+ /**
+ * Contains the opcode-dependent arguments for creating a HdmiCecMessageReported atom. Each
+ * field is initialized to a null-like value by default. Therefore, a freshly constructed
+ * instance of this object represents a HDMI CEC message whose type does not require any
+ * additional arguments.
+ */
+ private class MessageReportedSpecialArgs {
+ int mUserControlPressedCommand = HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN;
+ int mFeatureAbortOpcode = FEATURE_ABORT_OPCODE_UNKNOWN;
+ int mFeatureAbortReason = HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 7dc4d6e8efcf..bb6f14c0f6c4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -28,9 +28,11 @@ import android.os.Handler;
import android.os.IHwBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.stats.hdmi.HdmiStatsEnums;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -123,10 +125,14 @@ final class HdmiCecController {
private final NativeWrapper mNativeWrapperImpl;
+ private final HdmiCecAtomWriter mHdmiCecAtomWriter;
+
// Private constructor. Use HdmiCecController.create().
- private HdmiCecController(HdmiControlService service, NativeWrapper nativeWrapper) {
+ private HdmiCecController(
+ HdmiControlService service, NativeWrapper nativeWrapper, HdmiCecAtomWriter atomWriter) {
mService = service;
mNativeWrapperImpl = nativeWrapper;
+ mHdmiCecAtomWriter = atomWriter;
}
/**
@@ -134,21 +140,22 @@ final class HdmiCecController {
* inner device or has no device it will return {@code null}.
*
* <p>Declared as package-private, accessed by {@link HdmiControlService} only.
- * @param service {@link HdmiControlService} instance used to create internal handler
- * and to pass callback for incoming message or event.
+ * @param service {@link HdmiControlService} instance used to create internal handler
+ * and to pass callback for incoming message or event.
+ * @param atomWriter {@link HdmiCecAtomWriter} instance for writing atoms for metrics.
* @return {@link HdmiCecController} if device is initialized successfully. Otherwise,
* returns {@code null}.
*/
- static HdmiCecController create(HdmiControlService service) {
- return createWithNativeWrapper(service, new NativeWrapperImpl());
+ static HdmiCecController create(HdmiControlService service, HdmiCecAtomWriter atomWriter) {
+ return createWithNativeWrapper(service, new NativeWrapperImpl(), atomWriter);
}
/**
* A factory method with injection of native methods for testing.
*/
static HdmiCecController createWithNativeWrapper(
- HdmiControlService service, NativeWrapper nativeWrapper) {
- HdmiCecController controller = new HdmiCecController(service, nativeWrapper);
+ HdmiControlService service, NativeWrapper nativeWrapper, HdmiCecAtomWriter atomWriter) {
+ HdmiCecController controller = new HdmiCecController(service, nativeWrapper, atomWriter);
String nativePtr = nativeWrapper.nativeInit();
if (nativePtr == null) {
HdmiLogger.warning("Couldn't get tv.cec service.");
@@ -619,7 +626,7 @@ final class HdmiCecController {
public void run() {
HdmiLogger.debug("[S]:" + cecMessage);
byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
- int i = 0;
+ int retransmissionCount = 0;
int errorCode = SendMessageResult.SUCCESS;
do {
errorCode = mNativeWrapperImpl.nativeSendCecCommand(
@@ -627,20 +634,25 @@ final class HdmiCecController {
if (errorCode == SendMessageResult.SUCCESS) {
break;
}
- } while (i++ < HdmiConfig.RETRANSMISSION_COUNT);
+ } while (retransmissionCount++ < HdmiConfig.RETRANSMISSION_COUNT);
final int finalError = errorCode;
if (finalError != SendMessageResult.SUCCESS) {
Slog.w(TAG, "Failed to send " + cecMessage + " with errorCode=" + finalError);
}
- if (callback != null) {
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ mHdmiCecAtomWriter.messageReported(
+ cecMessage,
+ FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED__DIRECTION__OUTGOING,
+ finalError
+ );
+ if (callback != null) {
callback.onSendCompleted(finalError);
}
- });
- }
+ }
+ });
}
});
}
@@ -654,10 +666,39 @@ final class HdmiCecController {
HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
HdmiLogger.debug("[R]:" + command);
addCecMessageToHistory(true /* isReceived */, command);
+
+ mHdmiCecAtomWriter.messageReported(command,
+ incomingMessageDirection(srcAddress, dstAddress));
+
onReceiveCommand(command);
}
/**
+ * Computes the direction of an incoming message, as implied by the source and
+ * destination addresses. This will usually return INCOMING; if not, it can indicate a bug.
+ */
+ private int incomingMessageDirection(int srcAddress, int dstAddress) {
+ boolean sourceIsLocal = false;
+ boolean destinationIsLocal = false;
+ for (HdmiCecLocalDevice localDevice : getLocalDeviceList()) {
+ int logicalAddress = localDevice.getDeviceInfo().getLogicalAddress();
+ if (logicalAddress == srcAddress) {
+ sourceIsLocal = true;
+ }
+ if (logicalAddress == dstAddress) {
+ destinationIsLocal = true;
+ }
+ }
+
+ if (!sourceIsLocal && destinationIsLocal) {
+ return HdmiStatsEnums.INCOMING;
+ } else if (sourceIsLocal && destinationIsLocal) {
+ return HdmiStatsEnums.TO_SELF;
+ }
+ return HdmiStatsEnums.MESSAGE_DIRECTION_OTHER;
+ }
+
+ /**
* Called when a hotplug event issues.
*/
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 44b6a63faea1..b407234457a4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -397,6 +397,10 @@ public class HdmiControlService extends SystemService {
// Set to true if the logical address allocation is completed.
private boolean mAddressAllocated = false;
+ // Object that handles logging statsd atoms.
+ // Use getAtomWriter() instead of accessing directly, to allow dependency injection for testing.
+ private HdmiCecAtomWriter mAtomWriter = new HdmiCecAtomWriter();
+
// Buffer for processing the incoming cec messages while allocating logical addresses.
private final class CecMessageBuffer {
private List<HdmiCecMessage> mBuffer = new ArrayList<>();
@@ -509,7 +513,7 @@ public class HdmiControlService extends SystemService {
mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
if (mCecController == null) {
- mCecController = HdmiCecController.create(this);
+ mCecController = HdmiCecController.create(this, getAtomWriter());
}
if (mCecController != null) {
if (mHdmiControlEnabled) {
@@ -3233,6 +3237,10 @@ public class HdmiControlService extends SystemService {
mActiveSource.logicalAddress = logicalAddress;
mActiveSource.physicalAddress = physicalAddress;
}
+
+ getAtomWriter().activeSourceChanged(logicalAddress, physicalAddress,
+ HdmiUtils.pathRelationship(getPhysicalAddress(), physicalAddress));
+
// If the current device is a source device, check if the current Active Source matches
// the local device info. Set mIsActiveSource of the local device accordingly.
for (HdmiCecLocalDevice device : getAllLocalDevices()) {
@@ -3363,6 +3371,11 @@ public class HdmiControlService extends SystemService {
}
}
+ @VisibleForTesting
+ HdmiCecAtomWriter getAtomWriter() {
+ return mAtomWriter;
+ }
+
boolean isMhlInputChangeEnabled() {
synchronized (mLock) {
return mMhlInputChangeEnabled;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1b43db2a421d..68961d9c94d8 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -114,6 +114,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
@@ -2609,6 +2610,10 @@ public class LockSettingsService extends ILockSettings.Stub {
protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
LockscreenCredential credential, int userId) {
Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
+ Preconditions.checkState(
+ getSyntheticPasswordHandleLocked(userId) == SyntheticPasswordManager.DEFAULT_HANDLE,
+ "Cannot reinitialize SP");
+
final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
getGateKeeperService(), credentialHash, credential, userId);
onAuthTokenKnownForUser(userId, auth);
@@ -2669,7 +2674,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@VisibleForTesting
protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
- return true;
+ return getSyntheticPasswordHandleLocked(userId) == SyntheticPasswordManager.DEFAULT_HANDLE;
}
private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
@@ -3501,6 +3506,9 @@ public class LockSettingsService extends ILockSettings.Stub {
SyntheticPasswordManager.AuthenticationToken
authToken = new SyntheticPasswordManager.AuthenticationToken(spVersion);
authToken.recreateDirectly(syntheticPassword);
+ synchronized (mSpManager) {
+ mSpManager.verifyChallenge(getGateKeeperService(), authToken, 0L, userId);
+ }
onCredentialVerified(authToken, loadPasswordMetrics(authToken, userId), userId);
}
}
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index c6c80aef4432..8640dbcab33c 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -64,7 +64,6 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -168,12 +167,11 @@ public class ApkChecksums {
}
/**
- * Serialize checksums to file in binary format.
+ * Serialize checksums to the stream in binary format.
*/
- public static void writeChecksums(File file, ApkChecksum[] checksums)
+ public static void writeChecksums(OutputStream os, ApkChecksum[] checksums)
throws IOException, CertificateException {
- try (OutputStream os = new FileOutputStream(file);
- DataOutputStream dos = new DataOutputStream(os)) {
+ try (DataOutputStream dos = new DataOutputStream(os)) {
dos.writeInt(checksums.length);
for (ApkChecksum checksum : checksums) {
final String splitName = checksum.getSplitName();
@@ -190,6 +188,14 @@ public class ApkChecksums {
dos.writeInt(valueBytes.length);
dos.write(valueBytes);
+ final String packageName = checksum.getSourcePackageName();
+ if (packageName == null) {
+ dos.writeInt(-1);
+ } else {
+ dos.writeInt(packageName.length());
+ dos.writeUTF(packageName);
+ }
+
final Certificate cert = checksum.getSourceCertificate();
final byte[] certBytes = (cert == null) ? null : cert.getEncoded();
if (certBytes == null) {
@@ -218,9 +224,19 @@ public class ApkChecksums {
} else {
splitName = dis.readUTF();
}
+
final int kind = dis.readInt();
+
final byte[] valueBytes = new byte[dis.readInt()];
dis.read(valueBytes);
+
+ final String packageName;
+ if (dis.readInt() < 0) {
+ packageName = null;
+ } else {
+ packageName = dis.readUTF();
+ }
+
final byte[] certBytes;
final int certBytesLength = dis.readInt();
if (certBytesLength < 0) {
@@ -230,7 +246,7 @@ public class ApkChecksums {
dis.read(certBytes);
}
checksums[i] = new ApkChecksum(splitName, new Checksum(kind, valueBytes),
- certBytes);
+ packageName, certBytes);
}
return checksums;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 48efa5c31f2b..2a189c0ebb0c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -52,6 +52,7 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyEventLogger;
@@ -153,6 +154,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileFilter;
@@ -240,6 +242,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String ATTR_SIGNATURE = "signature";
private static final String ATTR_CHECKSUM_KIND = "checksumKind";
private static final String ATTR_CHECKSUM_VALUE = "checksumValue";
+ private static final String ATTR_CHECKSUM_PACKAGE = "checksumPackage";
private static final String ATTR_CHECKSUM_CERTIFICATE = "checksumCertificate";
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
@@ -394,10 +397,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
static class CertifiedChecksum {
final @NonNull Checksum mChecksum;
+ final @NonNull String mPackageName;
final @NonNull byte[] mCertificate;
- CertifiedChecksum(@NonNull Checksum checksum, @NonNull byte[] certificate) {
+ CertifiedChecksum(@NonNull Checksum checksum, @NonNull String packageName,
+ @NonNull byte[] certificate) {
mChecksum = checksum;
+ mPackageName = packageName;
mCertificate = certificate;
}
@@ -405,6 +411,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return mChecksum;
}
+ String getPackageName() {
+ return mPackageName;
+ }
+
byte[] getCertificate() {
return mCertificate;
}
@@ -951,23 +961,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- final PackageManagerInternal pmi = LocalServices.getService(
- PackageManagerInternal.class);
- final AndroidPackage callingInstaller = pmi.getPackage(Binder.getCallingUid());
+ final String initiatingPackageName = mInstallSource.initiatingPackageName;
+ final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+ appOps.checkPackage(Binder.getCallingUid(), initiatingPackageName);
+
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ final AndroidPackage callingInstaller = pmi.getPackage(initiatingPackageName);
if (callingInstaller == null) {
throw new IllegalStateException("Can't obtain calling installer's package.");
}
// Obtaining array of certificates used for signing the installer package.
- // According to V2/V3 signing schema, the first certificate corresponds to public key
- // in the signing block.
- Signature[] certs = callingInstaller.getSigningDetails().signatures;
+ final Signature[] certs = callingInstaller.getSigningDetails().signatures;
if (certs == null || certs.length == 0 || certs[0] == null) {
throw new IllegalStateException(
"Can't obtain calling installer package's certificates.");
}
- byte[] mainCertificateBytes = certs[0].toByteArray();
+ // According to V2/V3 signing schema, the first certificate corresponds to the public key
+ // in the signing block.
+ final byte[] mainCertificateBytes = certs[0].toByteArray();
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -979,7 +992,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
fileChecksums = new ArrayList<>();
mChecksums.put(name, fileChecksums);
}
- fileChecksums.add(new CertifiedChecksum(checksum, mainCertificateBytes));
+ fileChecksums.add(new CertifiedChecksum(checksum, initiatingPackageName,
+ mainCertificateBytes));
}
}
}
@@ -2633,7 +2647,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
for (int i = 0, size = checksums.size(); i < size; ++i) {
CertifiedChecksum checksum = checksums.get(i);
result[i] = new ApkChecksum(splitName, checksum.getChecksum(),
- checksum.getCertificate());
+ checksum.getPackageName(), checksum.getCertificate());
}
return result;
}
@@ -2651,11 +2665,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- final File targetDigestsFile = new File(stageDir,
- ApkChecksums.buildDigestsPathForApk(targetFile.getName()));
- try {
- ApkChecksums.writeChecksums(targetDigestsFile,
- createApkChecksums(splitName, checksums));
+ final String targetDigestsPath = ApkChecksums.buildDigestsPathForApk(targetFile.getName());
+ final File targetDigestsFile = new File(stageDir, targetDigestsPath);
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ ApkChecksums.writeChecksums(os, createApkChecksums(splitName, checksums));
+ final byte[] checksumsBytes = os.toByteArray();
+
+ if (!isIncrementalInstallation() || mIncrementalFileStorages == null) {
+ FileUtils.bytesToFile(targetDigestsFile.getAbsolutePath(), checksumsBytes);
+ } else {
+ mIncrementalFileStorages.makeFile(targetDigestsPath, checksumsBytes);
+ }
} catch (CertificateException e) {
throw new PackageManagerException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
"Failed to encode certificate for " + mPackageName, e);
@@ -3975,6 +3995,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeIntAttribute(out, ATTR_CHECKSUM_KIND, checksum.getChecksum().getKind());
writeByteArrayAttribute(out, ATTR_CHECKSUM_VALUE,
checksum.getChecksum().getValue());
+ writeStringAttribute(out, ATTR_CHECKSUM_PACKAGE, checksum.getPackageName());
writeByteArrayAttribute(out, ATTR_CHECKSUM_CERTIFICATE,
checksum.getCertificate());
out.endTag(null, TAG_SESSION_CHECKSUM);
@@ -4127,6 +4148,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final CertifiedChecksum certifiedChecksum = new CertifiedChecksum(
new Checksum(readIntAttribute(in, ATTR_CHECKSUM_KIND, 0),
readByteArrayAttribute(in, ATTR_CHECKSUM_VALUE)),
+ readStringAttribute(in, ATTR_CHECKSUM_PACKAGE),
readByteArrayAttribute(in, ATTR_CHECKSUM_CERTIFICATE));
List<CertifiedChecksum> certifiedChecksums = checksums.get(fileName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2f26f39d0444..697c31a78ec7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1736,15 +1736,14 @@ public class PackageManagerService extends IPackageManager.Stub
int i = 0; // filling out the above arrays
for (int n = 0; n < mPendingBroadcasts.userIdCount(); n++) {
- int packageUserId = mPendingBroadcasts.userIdAt(n);
- Iterator<Map.Entry<String, ArrayList<String>>> it
- = mPendingBroadcasts.packagesForUserId(packageUserId)
- .entrySet().iterator();
- while (it.hasNext() && i < size) {
- Map.Entry<String, ArrayList<String>> ent = it.next();
- packages[i] = ent.getKey();
- components[i] = ent.getValue();
- PackageSetting ps = mSettings.mPackages.get(ent.getKey());
+ final int packageUserId = mPendingBroadcasts.userIdAt(n);
+ final ArrayMap<String, ArrayList<String>> componentsToBroadcast =
+ mPendingBroadcasts.packagesForUserId(packageUserId);
+ final int numComponents = componentsToBroadcast.size();
+ for (int index = 0; i < size && index < numComponents; index++) {
+ packages[i] = componentsToBroadcast.keyAt(index);
+ components[i] = componentsToBroadcast.valueAt(index);
+ final PackageSetting ps = mSettings.mPackages.get(packages[i]);
uids[i] = (ps != null)
? UserHandle.getUid(packageUserId, ps.appId)
: -1;
@@ -3235,17 +3234,18 @@ public class PackageManagerService extends IPackageManager.Stub
final List<String> stubSystemApps = new ArrayList<>();
if (!mOnlyCore) {
// do this first before mucking with mPackages for the "expecting better" case
- final Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator();
- while (pkgIterator.hasNext()) {
- final AndroidPackage pkg = pkgIterator.next();
+ final int numPackages = mPackages.size();
+ for (int index = 0; index < numPackages; index++) {
+ final AndroidPackage pkg = mPackages.valueAt(index);
if (pkg.isStub()) {
stubSystemApps.add(pkg.getPackageName());
}
}
- final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
- while (psit.hasNext()) {
- PackageSetting ps = psit.next();
+ // Iterates PackageSettings in reversed order because the item could be removed
+ // during the iteration.
+ for (int index = mSettings.mPackages.size() - 1; index >= 0; index--) {
+ final PackageSetting ps = mSettings.mPackages.valueAt(index);
/*
* If this is not a system app, it can't be a
@@ -3282,7 +3282,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
- psit.remove();
+ mSettings.mPackages.removeAt(index);
logCriticalInfo(Log.WARN, "System package " + ps.name
+ " no longer exists; it's data will be wiped");
@@ -6349,10 +6349,9 @@ public class PackageManagerService extends IPackageManager.Stub
final SharedUserSetting sus = (SharedUserSetting) obj;
final int N = sus.packages.size();
String[] res = new String[N];
- final Iterator<PackageSetting> it = sus.packages.iterator();
int i = 0;
- while (it.hasNext()) {
- PackageSetting ps = it.next();
+ for (int index = 0; index < N; index++) {
+ final PackageSetting ps = sus.packages.valueAt(index);
if (ps.getInstalled(userId)) {
res[i++] = ps.name;
}
@@ -6508,9 +6507,10 @@ public class PackageManagerService extends IPackageManager.Stub
final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
- final Iterator<PackageSetting> it = sus.packages.iterator();
- while (it.hasNext()) {
- if (it.next().isPrivileged()) {
+ final int numPackages = sus.packages.size();
+ for (int index = 0; index < numPackages; index++) {
+ final PackageSetting ps = sus.packages.valueAt(index);
+ if (ps.isPrivileged()) {
return true;
}
}
@@ -9009,10 +9009,10 @@ public class PackageManagerService extends IPackageManager.Stub
// reader
synchronized (mLock) {
- final Iterator<AndroidPackage> i = mPackages.values().iterator();
+ final int numPackages = mPackages.size();
final int userId = UserHandle.getCallingUserId();
- while (i.hasNext()) {
- final AndroidPackage p = i.next();
+ for (int index = 0; index < numPackages; index++) {
+ final AndroidPackage p = mPackages.valueAt(index);
final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
&& !p.isDirectBootAware();
@@ -9170,9 +9170,9 @@ public class PackageManagerService extends IPackageManager.Stub
// reader
synchronized (mLock) {
- final Iterator<ParsedInstrumentation> i = mInstrumentation.values().iterator();
- while (i.hasNext()) {
- final ParsedInstrumentation p = i.next();
+ final int numInstrumentations = mInstrumentation.size();
+ for (int index = 0; index < numInstrumentations; index++) {
+ final ParsedInstrumentation p = mInstrumentation.valueAt(index);
if (targetPackage == null
|| targetPackage.equals(p.getTargetPackage())) {
String packageName = p.getPackageName();
@@ -19822,9 +19822,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
- final Iterator<PackageSetting> it = sus.packages.iterator();
- while (it.hasNext()) {
- final PackageSetting ps = it.next();
+ final int numPackages = sus.packages.size();
+ for (int index = 0; index < numPackages; index++) {
+ final PackageSetting ps = sus.packages.valueAt(index);
if (ps.pkg != null) {
int v = ps.pkg.getTargetSdkVersion();
if (v < vers) vers = v;
@@ -22120,9 +22120,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
boolean printedHeader = false;
- final Iterator<String> it = mSharedLibraries.keySet().iterator();
- while (it.hasNext()) {
- String libName = it.next();
+ final int numSharedLibraries = mSharedLibraries.size();
+ for (int index = 0; index < numSharedLibraries; index++) {
+ final String libName = mSharedLibraries.keyAt(index);
LongSparseArray<SharedLibraryInfo> versionedLib
= mSharedLibraries.get(libName);
if (versionedLib == null) {
@@ -23751,9 +23751,9 @@ public class PackageManagerService extends IPackageManager.Stub
private void removeUnusedPackagesLPw(UserManagerService userManager, final int userId) {
final boolean DEBUG_CLEAN_APKS = false;
int [] users = userManager.getUserIds();
- Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
- while (psit.hasNext()) {
- PackageSetting ps = psit.next();
+ final int numPackages = mSettings.mPackages.size();
+ for (int index = 0; index < numPackages; index++) {
+ final PackageSetting ps = mSettings.mPackages.valueAt(index);
if (ps.pkg == null) {
continue;
}
@@ -25456,11 +25456,11 @@ public class PackageManagerService extends IPackageManager.Stub
}
ArraySet<PackageSetting> packages = packageSetting.sharedUser.packages;
- String[] res = new String[packages.size()];
- final Iterator<PackageSetting> it = packages.iterator();
+ final int numPackages = packages.size();
+ String[] res = new String[numPackages];
int i = 0;
- while (it.hasNext()) {
- PackageSetting ps = it.next();
+ for (int index = 0; index < numPackages; index++) {
+ final PackageSetting ps = packages.valueAt(index);
if (ps.getInstalled(userId)) {
res[i++] = ps.name;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index 2bbca79741bd..1814a8e6322e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -27,6 +27,8 @@ import android.service.dataloader.DataLoaderService;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+
import libcore.io.IoUtils;
import java.io.IOException;
@@ -112,7 +114,9 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
}
- static class Metadata {
+ /** @hide */
+ @VisibleForTesting
+ public static class Metadata {
/**
* Full files read from stdin.
*/
@@ -137,7 +141,9 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
return new Metadata(STDIN, fileId);
}
- static Metadata forLocalFile(String filePath) {
+ /** @hide */
+ @VisibleForTesting
+ public static Metadata forLocalFile(String filePath) {
return new Metadata(LOCAL_FILE, filePath);
}
@@ -163,7 +169,9 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
return new Metadata(mode, data);
}
- byte[] toByteArray() {
+ /** @hide */
+ @VisibleForTesting
+ public byte[] toByteArray() {
byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
byte[] result = new byte[1 + dataBytes.length];
result[0] = this.mMode;
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 485868237895..7d48d0a6e266 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -33,16 +33,13 @@
"name": "CtsContentTestCases",
"options": [
{
- "include-filter": "android.content.pm.cts.ChecksumsTest"
- },
- {
- "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
},
{
- "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest"
+ "exclude-annotation": "org.junit.Ignore"
},
{
- "include-filter": "android.content.pm.cts.PackageManagerTest"
+ "include-filter": "android.content.pm.cts"
}
]
},
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 2f9e199bc506..aa327ba02356 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -137,6 +137,7 @@ import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerService;
import com.android.server.pm.ApexManager;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
@@ -901,6 +902,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
private int checkPermissionImpl(String permName, String pkgName, int userId) {
+ try {
+ enforceCrossUserOrProfilePermission(Binder.getCallingUid(), userId,
+ false, false, "checkPermissionImpl");
+ } catch (Exception e) {
+ Slog.e(TAG, "Invalid cross user access", e);
+ EventLog.writeEvent(0x534e4554, "153996875", "checkPermissionImpl", pkgName);
+
+ throw e;
+ }
+
final AndroidPackage pkg = mPackageManagerInt.getPackage(pkgName);
if (pkg == null) {
return PackageManager.PERMISSION_DENIED;
@@ -978,6 +989,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
private int checkUidPermissionImpl(String permName, int uid) {
+ try {
+ enforceCrossUserOrProfilePermission(Binder.getCallingUid(), UserHandle.getUserId(uid),
+ false, false, "checkUidPermissionImpl");
+ } catch (Exception e) {
+ Slog.e(TAG, "Invalid cross user access", e);
+ EventLog.writeEvent(0x534e4554, "153996875", "checkUidPermissionImpl", uid);
+
+ throw e;
+ }
+
final AndroidPackage pkg = mPackageManagerInt.getPackage(uid);
return checkUidPermissionInternal(pkg, uid, permName);
}
@@ -4508,7 +4529,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
final int callingUserId = UserHandle.getUserId(callingUid);
if (hasCrossUserPermission(
- callingUid, callingUserId, userId, requireFullPermission,
+ Binder.getCallingPid(), callingUid, callingUserId, userId, requireFullPermission,
requirePermissionWhenSameUser)) {
return;
}
@@ -4535,53 +4556,79 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId,
boolean requireFullPermission, boolean checkShell,
String message) {
+ int callingPid = Binder.getCallingPid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+
if (userId < 0) {
throw new IllegalArgumentException("Invalid userId " + userId);
}
- if (checkShell) {
- PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt,
- UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
- }
- final int callingUserId = UserHandle.getUserId(callingUid);
- if (hasCrossUserPermission(callingUid, callingUserId, userId, requireFullPermission,
- /*requirePermissionWhenSameUser= */ false)) {
+
+ if (callingUserId == userId) {
return;
}
- final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId);
- if (isSameProfileGroup && PermissionChecker.checkPermissionForPreflight(
- mContext,
- android.Manifest.permission.INTERACT_ACROSS_PROFILES,
- PermissionChecker.PID_UNKNOWN,
- callingUid,
- mPackageManagerInt.getPackage(callingUid).getPackageName())
- == PermissionChecker.PERMISSION_GRANTED) {
+
+ // Prevent endless loop between when checking permission while checking a permission
+ if (callingPid == ActivityManagerService.MY_PID) {
return;
}
+
+ long token = Binder.clearCallingIdentity();
+ try {
+ if (checkShell) {
+ PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt,
+ UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
+ }
+ if (hasCrossUserPermission(callingPid, callingUid, callingUserId, userId,
+ requireFullPermission, /*requirePermissionWhenSameUser= */ false)) {
+ return;
+ }
+ final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId);
+
+ if (isSameProfileGroup) {
+ AndroidPackage callingPkg = mPackageManagerInt.getPackage(callingUid);
+ String callingPkgName = null;
+ if (callingPkg != null) {
+ callingPkgName = callingPkg.getPackageName();
+ }
+
+ if (PermissionChecker.checkPermissionForPreflight(
+ mContext,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ PermissionChecker.PID_UNKNOWN,
+ callingUid,
+ callingPkgName)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+
String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage(
callingUid, userId, message, requireFullPermission, isSameProfileGroup);
Slog.w(TAG, errorMessage);
throw new SecurityException(errorMessage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
- private boolean hasCrossUserPermission(
- int callingUid, int callingUserId, int userId, boolean requireFullPermission,
- boolean requirePermissionWhenSameUser) {
+ private boolean hasCrossUserPermission(int callingPid, int callingUid, int callingUserId,
+ int userId, boolean requireFullPermission, boolean requirePermissionWhenSameUser) {
if (!requirePermissionWhenSameUser && userId == callingUserId) {
return true;
}
if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
return true;
}
- if (requireFullPermission) {
- return hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+
+ if (!requireFullPermission) {
+ if (mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
}
- return hasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS);
- }
- private boolean hasPermission(String permission) {
- return mContext.checkCallingOrSelfPermission(permission)
- == PackageManager.PERMISSION_GRANTED;
+ return mContext.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
}
private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
index c0d71ac26853..65dc320eadc2 100644
--- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
@@ -18,21 +18,24 @@
]
},
{
- "name": "CtsAppSecurityHostTestCases",
+ "name": "CtsPermission2TestCases",
"options": [
{
- "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission"
+ "include-filter": "android.permission2.cts.RestrictedPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest"
}
]
},
{
- "name": "CtsPermission2TestCases",
+ "name": "CtsPermissionHostTestCases"
+ },
+ {
+ "name": "CtsAppSecurityHostTestCases",
"options": [
{
- "include-filter": "android.permission2.cts.RestrictedPermissionsTest"
- },
- {
- "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest"
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission"
}
]
},
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java b/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
index 5def7621c148..a90053a23dea 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
@@ -17,11 +17,28 @@
package com.android.server.soundtrigger_middleware;
import android.media.ICaptureStateListener;
-import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
+import android.media.soundtrigger_middleware.ISoundTriggerCallback;
+import android.media.soundtrigger_middleware.ISoundTriggerModule;
+import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
/**
- * This interface unifies ISoundTriggerMiddlewareService with ICaptureStateListener.
+ * This interface unifies methods from ISoundTriggerMiddlewareService and ICaptureStateListener.
+ *
+ * The ISoundTriggerMiddlewareService have been modified to exclude identity information and the
+ * RemoteException signature, both of which are only relevant at the service boundary layer.
*/
-public interface ISoundTriggerMiddlewareInternal extends ISoundTriggerMiddlewareService,
- ICaptureStateListener {
+public interface ISoundTriggerMiddlewareInternal extends ICaptureStateListener {
+ /**
+ * Query the available modules and their capabilities.
+ */
+ public SoundTriggerModuleDescriptor[] listModules();
+
+ /**
+ * Attach to one of the available modules.
+ *
+ * listModules() must be called prior to calling this method and the provided handle must be
+ * one of the handles from the returned list.
+ */
+ public ISoundTriggerModule attach(int handle,
+ ISoundTriggerCallback callback);
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java
index 761858ccd238..eced8940947a 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java
@@ -21,6 +21,7 @@ import android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback;
import android.hardware.soundtrigger.V2_3.ModelParameterRange;
import android.hardware.soundtrigger.V2_3.Properties;
import android.hardware.soundtrigger.V2_3.RecognitionConfig;
+import android.media.soundtrigger_middleware.Status;
import android.os.DeadObjectException;
import android.os.IHwBinder;
import android.os.RemoteException;
@@ -195,10 +196,10 @@ public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 {
if (e.getCause() instanceof DeadObjectException) {
// Server is dead, no need to reboot.
Log.e(TAG, "HAL died");
- } else {
- Log.e(TAG, "Exception caught from HAL, rebooting HAL");
- rebootHal();
+ throw new RecoverableException(Status.DEAD_OBJECT);
}
+ Log.e(TAG, "Exception caught from HAL, rebooting HAL");
+ rebootHal();
throw e;
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index 8b6ed1ff5081..2ef0759719fc 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -18,8 +18,9 @@ package com.android.server.soundtrigger_middleware;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.media.permission.Identity;
+import android.media.permission.IdentityContext;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
-import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.ModelParameterRange;
import android.media.soundtrigger_middleware.PhraseRecognitionEvent;
@@ -28,17 +29,15 @@ import android.media.soundtrigger_middleware.RecognitionConfig;
import android.media.soundtrigger_middleware.RecognitionEvent;
import android.media.soundtrigger_middleware.SoundModel;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
-import android.os.Binder;
import android.os.IBinder;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
-import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
+import java.util.Objects;
/**
* An ISoundTriggerMiddlewareService decorator, which adds logging of all API calls (and
@@ -71,7 +70,8 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
@Override
- public @NonNull SoundTriggerModuleDescriptor[] listModules() throws RemoteException {
+ public @NonNull
+ SoundTriggerModuleDescriptor[] listModules() {
try {
SoundTriggerModuleDescriptor[] result = mDelegate.listModules();
logReturn("listModules", result);
@@ -83,12 +83,13 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
@Override
- public @NonNull ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback)
- throws RemoteException {
+ public @NonNull
+ ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback) {
try {
- ISoundTriggerModule result = mDelegate.attach(handle, new CallbackLogging(callback));
+ ModuleLogging result = new ModuleLogging(callback);
+ result.attach(mDelegate.attach(handle, result.getCallbackWrapper()));
logReturn("attach", result, handle, callback);
- return new ModuleLogging(result);
+ return result;
} catch (Exception e) {
logException("attach", e, handle, callback);
throw e;
@@ -106,7 +107,8 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
}
- @Override public IBinder asBinder() {
+ @Override
+ public IBinder asBinder() {
throw new UnsupportedOperationException(
"This implementation is not inteded to be used directly with Binder.");
}
@@ -118,94 +120,33 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
private void logException(String methodName, Exception ex, Object... args) {
- logExceptionWithObject(this, methodName, ex, args);
+ logExceptionWithObject(this, IdentityContext.get(), methodName, ex, args);
}
private void logReturn(String methodName, Object retVal, Object... args) {
- logReturnWithObject(this, methodName, retVal, args);
+ logReturnWithObject(this, IdentityContext.get(), methodName, retVal, args);
}
private void logVoidReturn(String methodName, Object... args) {
- logVoidReturnWithObject(this, methodName, args);
+ logVoidReturnWithObject(this, IdentityContext.get(), methodName, args);
}
- private class CallbackLogging implements ISoundTriggerCallback {
- private final ISoundTriggerCallback mDelegate;
-
- private CallbackLogging(ISoundTriggerCallback delegate) {
- mDelegate = delegate;
- }
-
- @Override
- public void onRecognition(int modelHandle, RecognitionEvent event) throws RemoteException {
- try {
- mDelegate.onRecognition(modelHandle, event);
- logVoidReturn("onRecognition", modelHandle, event);
- } catch (Exception e) {
- logException("onRecognition", e, modelHandle, event);
- throw e;
- }
- }
-
- @Override
- public void onPhraseRecognition(int modelHandle, PhraseRecognitionEvent event)
- throws RemoteException {
- try {
- mDelegate.onPhraseRecognition(modelHandle, event);
- logVoidReturn("onPhraseRecognition", modelHandle, event);
- } catch (Exception e) {
- logException("onPhraseRecognition", e, modelHandle, event);
- throw e;
- }
- }
-
- @Override
- public void onRecognitionAvailabilityChange(boolean available) throws RemoteException {
- try {
- mDelegate.onRecognitionAvailabilityChange(available);
- logVoidReturn("onRecognitionAvailabilityChange", available);
- } catch (Exception e) {
- logException("onRecognitionAvailabilityChange", e, available);
- throw e;
- }
- }
-
- @Override
- public void onModuleDied() throws RemoteException {
- try {
- mDelegate.onModuleDied();
- logVoidReturn("onModuleDied");
- } catch (Exception e) {
- logException("onModuleDied", e);
- throw e;
- }
- }
-
- private void logException(String methodName, Exception ex, Object... args) {
- logExceptionWithObject(this, methodName, ex, args);
- }
+ private class ModuleLogging implements ISoundTriggerModule {
+ private ISoundTriggerModule mDelegate;
+ private final @NonNull CallbackLogging mCallbackWrapper;
+ private final @NonNull Identity mOriginatorIdentity;
- private void logVoidReturn(String methodName, Object... args) {
- logVoidReturnWithObject(this, methodName, args);
+ ModuleLogging(@NonNull ISoundTriggerCallback callback) {
+ mCallbackWrapper = new CallbackLogging(callback);
+ mOriginatorIdentity = IdentityContext.getNonNull();
}
- @Override
- public IBinder asBinder() {
- return mDelegate.asBinder();
- }
-
- // Override toString() in order to have the delegate's ID in it.
- @Override
- public String toString() {
- return mDelegate.toString();
+ void attach(@NonNull ISoundTriggerModule delegate) {
+ mDelegate = delegate;
}
- }
-
- private class ModuleLogging implements ISoundTriggerModule {
- private final ISoundTriggerModule mDelegate;
- private ModuleLogging(ISoundTriggerModule delegate) {
- mDelegate = delegate;
+ ISoundTriggerCallback getCallbackWrapper() {
+ return mCallbackWrapper;
}
@Override
@@ -334,19 +275,92 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
// Override toString() in order to have the delegate's ID in it.
@Override
public String toString() {
- return mDelegate.toString();
+ return Objects.toString(mDelegate);
}
private void logException(String methodName, Exception ex, Object... args) {
- logExceptionWithObject(this, methodName, ex, args);
+ logExceptionWithObject(this, mOriginatorIdentity, methodName, ex, args);
}
private void logReturn(String methodName, Object retVal, Object... args) {
- logReturnWithObject(this, methodName, retVal, args);
+ logReturnWithObject(this, mOriginatorIdentity, methodName, retVal, args);
}
private void logVoidReturn(String methodName, Object... args) {
- logVoidReturnWithObject(this, methodName, args);
+ logVoidReturnWithObject(this, mOriginatorIdentity, methodName, args);
+ }
+
+ private class CallbackLogging implements ISoundTriggerCallback {
+ private final ISoundTriggerCallback mCallbackDelegate;
+
+ private CallbackLogging(ISoundTriggerCallback delegate) {
+ mCallbackDelegate = delegate;
+ }
+
+ @Override
+ public void onRecognition(int modelHandle, RecognitionEvent event)
+ throws RemoteException {
+ try {
+ mCallbackDelegate.onRecognition(modelHandle, event);
+ logVoidReturn("onRecognition", modelHandle, event);
+ } catch (Exception e) {
+ logException("onRecognition", e, modelHandle, event);
+ throw e;
+ }
+ }
+
+ @Override
+ public void onPhraseRecognition(int modelHandle, PhraseRecognitionEvent event)
+ throws RemoteException {
+ try {
+ mCallbackDelegate.onPhraseRecognition(modelHandle, event);
+ logVoidReturn("onPhraseRecognition", modelHandle, event);
+ } catch (Exception e) {
+ logException("onPhraseRecognition", e, modelHandle, event);
+ throw e;
+ }
+ }
+
+ @Override
+ public void onRecognitionAvailabilityChange(boolean available) throws RemoteException {
+ try {
+ mCallbackDelegate.onRecognitionAvailabilityChange(available);
+ logVoidReturn("onRecognitionAvailabilityChange", available);
+ } catch (Exception e) {
+ logException("onRecognitionAvailabilityChange", e, available);
+ throw e;
+ }
+ }
+
+ @Override
+ public void onModuleDied() throws RemoteException {
+ try {
+ mCallbackDelegate.onModuleDied();
+ logVoidReturn("onModuleDied");
+ } catch (Exception e) {
+ logException("onModuleDied", e);
+ throw e;
+ }
+ }
+
+ private void logException(String methodName, Exception ex, Object... args) {
+ logExceptionWithObject(this, mOriginatorIdentity, methodName, ex, args);
+ }
+
+ private void logVoidReturn(String methodName, Object... args) {
+ logVoidReturnWithObject(this, mOriginatorIdentity, methodName, args);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mCallbackDelegate.asBinder();
+ }
+
+ // Override toString() in order to have the delegate's ID in it.
+ @Override
+ public String toString() {
+ return Objects.toString(mCallbackDelegate);
+ }
}
}
@@ -386,34 +400,37 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
return builder.toString();
}
- private void logReturnWithObject(@NonNull Object object, String methodName,
+ private void logReturnWithObject(@NonNull Object object, @Nullable Identity originatorIdentity,
+ String methodName,
@Nullable Object retVal,
@NonNull Object[] args) {
- final String message = String.format("%s[this=%s, caller=%d/%d](%s) -> %s", methodName,
+ final String message = String.format("%s[this=%s, client=%s](%s) -> %s", methodName,
object,
- Binder.getCallingUid(), Binder.getCallingPid(),
+ printObject(originatorIdentity),
printArgs(args),
printObject(retVal));
Log.i(TAG, message);
appendMessage(message);
}
- private void logVoidReturnWithObject(@NonNull Object object, @NonNull String methodName,
+ private void logVoidReturnWithObject(@NonNull Object object,
+ @Nullable Identity originatorIdentity, @NonNull String methodName,
@NonNull Object[] args) {
- final String message = String.format("%s[this=%s, caller=%d/%d](%s)", methodName,
+ final String message = String.format("%s[this=%s, client=%s](%s)", methodName,
object,
- Binder.getCallingUid(), Binder.getCallingPid(),
+ printObject(originatorIdentity),
printArgs(args));
Log.i(TAG, message);
appendMessage(message);
}
- private void logExceptionWithObject(@NonNull Object object, @NonNull String methodName,
+ private void logExceptionWithObject(@NonNull Object object,
+ @Nullable Identity originatorIdentity, @NonNull String methodName,
@NonNull Exception ex,
Object[] args) {
- final String message = String.format("%s[this=%s, caller=%d/%d](%s) threw", methodName,
+ final String message = String.format("%s[this=%s, client=%s](%s) threw", methodName,
object,
- Binder.getCallingUid(), Binder.getCallingPid(),
+ printObject(originatorIdentity),
printArgs(args));
Log.e(TAG, message, ex);
appendMessage(message + " " + ex.toString());
@@ -429,7 +446,8 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
}
- @Override public void dump(PrintWriter pw) {
+ @Override
+ public void dump(PrintWriter pw) {
pw.println();
pw.println("=========================================");
pw.println("Last events");
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
new file mode 100644
index 000000000000..7b6c6561ccf1
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -0,0 +1,348 @@
+/*
+ * 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.soundtrigger_middleware;
+
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.RECORD_AUDIO;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.PermissionChecker;
+import android.media.permission.Identity;
+import android.media.permission.IdentityContext;
+import android.media.permission.PermissionUtil;
+import android.media.soundtrigger_middleware.ISoundTriggerCallback;
+import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
+import android.media.soundtrigger_middleware.ISoundTriggerModule;
+import android.media.soundtrigger_middleware.ModelParameterRange;
+import android.media.soundtrigger_middleware.PhraseRecognitionEvent;
+import android.media.soundtrigger_middleware.PhraseSoundModel;
+import android.media.soundtrigger_middleware.RecognitionConfig;
+import android.media.soundtrigger_middleware.RecognitionEvent;
+import android.media.soundtrigger_middleware.SoundModel;
+import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
+import android.media.soundtrigger_middleware.Status;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+
+/**
+ * This is a decorator of an {@link ISoundTriggerMiddlewareService}, which enforces permissions.
+ * <p>
+ * Every public method in this class, overriding an interface method, must follow a similar
+ * pattern:
+ * <code><pre>
+ * @Override public T method(S arg) {
+ * // Permission check.
+ * enforcePermissions*(...);
+ * return mDelegate.method(arg);
+ * }
+ * </pre></code>
+ *
+ * {@hide}
+ */
+public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddlewareInternal, Dumpable {
+ private static final String TAG = "SoundTriggerMiddlewarePermission";
+
+ private final @NonNull ISoundTriggerMiddlewareInternal mDelegate;
+ private final @NonNull Context mContext;
+
+ public SoundTriggerMiddlewarePermission(
+ @NonNull ISoundTriggerMiddlewareInternal delegate, @NonNull Context context) {
+ mDelegate = delegate;
+ mContext = context;
+ }
+
+ @Override
+ public @NonNull
+ SoundTriggerModuleDescriptor[] listModules() {
+ Identity identity = getIdentity();
+ enforcePermissionsForPreflight(identity);
+ return mDelegate.listModules();
+ }
+
+ @Override
+ public @NonNull
+ ISoundTriggerModule attach(int handle,
+ @NonNull ISoundTriggerCallback callback) {
+ Identity identity = getIdentity();
+ enforcePermissionsForPreflight(identity);
+ ModuleWrapper wrapper = new ModuleWrapper(identity, callback);
+ return wrapper.attach(mDelegate.attach(handle, wrapper.getCallbackWrapper()));
+ }
+
+ @Override
+ public void setCaptureState(boolean active) throws RemoteException {
+ // This is an internal call. No permissions needed.
+ mDelegate.setCaptureState(active);
+ }
+
+ // Override toString() in order to have the delegate's ID in it.
+ @Override
+ public String toString() {
+ return Objects.toString(mDelegate);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ throw new UnsupportedOperationException(
+ "This implementation is not inteded to be used directly with Binder.");
+ }
+
+ /**
+ * Get the identity context, or throws an InternalServerError if it has not been established.
+ *
+ * @return The identity.
+ */
+ private static @NonNull
+ Identity getIdentity() {
+ return IdentityContext.getNonNull();
+ }
+
+ /**
+ * Throws a {@link SecurityException} if originator permanently doesn't have the given
+ * permission,
+ * or a {@link ServiceSpecificException} with a {@link Status#TEMPORARY_PERMISSION_DENIED} if
+ * originator temporarily doesn't have the right permissions to use this service.
+ */
+ private void enforcePermissionsForPreflight(@NonNull Identity identity) {
+ enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO);
+ enforcePermissionForPreflight(mContext, identity, CAPTURE_AUDIO_HOTWORD);
+ }
+
+ /**
+ * Throws a {@link SecurityException} iff the originator has permission to receive data.
+ */
+ void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
+ enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO, reason);
+ enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
+ reason);
+ }
+
+ /**
+ * Throws a {@link SecurityException} iff the given identity has given permission to receive
+ * data.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param identity The identity to check.
+ * @param permission The identifier of the permission we want to check.
+ * @param reason The reason why we're requesting the permission, for auditing purposes.
+ */
+ private static void enforcePermissionForDataDelivery(@NonNull Context context,
+ @NonNull Identity identity,
+ @NonNull String permission, @NonNull String reason) {
+ // TODO(ytai): We're temporarily ignoring proc state until we have a proper permission that
+ // represents being able to use the microphone in the background. Otherwise, some of our
+ // existing use-cases would break.
+ final int status = PermissionUtil.checkPermissionForDataDeliveryIgnoreProcState(context,
+ identity, permission, reason);
+ if (status != PermissionChecker.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ String.format("Failed to obtain permission %s for identity %s", permission,
+ ObjectPrinter.print(identity, true, 16)));
+ }
+ }
+
+ /**
+ * Throws a {@link SecurityException} if originator permanently doesn't have the given
+ * permission, or a {@link ServiceSpecificException} with a {@link
+ * Status#TEMPORARY_PERMISSION_DENIED} if caller originator doesn't have the given permission.
+ *
+ * @param context A {@link Context}, used for permission checks.
+ * @param identity The identity to check.
+ * @param permission The identifier of the permission we want to check.
+ */
+ private static void enforcePermissionForPreflight(@NonNull Context context,
+ @NonNull Identity identity, @NonNull String permission) {
+ final int status = PermissionUtil.checkPermissionForPreflight(context, identity,
+ permission);
+ switch (status) {
+ case PermissionChecker.PERMISSION_GRANTED:
+ return;
+ case PermissionChecker.PERMISSION_HARD_DENIED:
+ throw new SecurityException(
+ String.format("Failed to obtain permission %s for identity %s", permission,
+ ObjectPrinter.print(identity, true, 16)));
+ case PermissionChecker.PERMISSION_SOFT_DENIED:
+ throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED,
+ String.format("Failed to obtain permission %s for identity %s", permission,
+ ObjectPrinter.print(identity, true, 16)));
+ default:
+ throw new RuntimeException("Unexpected perimission check result.");
+ }
+ }
+
+
+ @Override
+ public void dump(PrintWriter pw) {
+ if (mDelegate instanceof Dumpable) {
+ ((Dumpable) mDelegate).dump(pw);
+ }
+ }
+
+ /**
+ * A wrapper around an {@link ISoundTriggerModule} implementation, to address the same aspects
+ * mentioned in {@link SoundTriggerModule} above. This class follows the same conventions.
+ */
+ private class ModuleWrapper extends ISoundTriggerModule.Stub {
+ private ISoundTriggerModule mDelegate;
+ private final @NonNull Identity mOriginatorIdentity;
+ private final @NonNull CallbackWrapper mCallbackWrapper;
+
+ ModuleWrapper(@NonNull Identity originatorIdentity,
+ @NonNull ISoundTriggerCallback callback) {
+ mOriginatorIdentity = originatorIdentity;
+ mCallbackWrapper = new CallbackWrapper(callback);
+ }
+
+ ModuleWrapper attach(@NonNull ISoundTriggerModule delegate) {
+ mDelegate = delegate;
+ return this;
+ }
+
+ ISoundTriggerCallback getCallbackWrapper() {
+ return mCallbackWrapper;
+ }
+
+ @Override
+ public int loadModel(@NonNull SoundModel model) throws RemoteException {
+ enforcePermissions();
+ return mDelegate.loadModel(model);
+ }
+
+ @Override
+ public int loadPhraseModel(@NonNull PhraseSoundModel model) throws RemoteException {
+ enforcePermissions();
+ return mDelegate.loadPhraseModel(model);
+ }
+
+ @Override
+ public void unloadModel(int modelHandle) throws RemoteException {
+ enforcePermissions();
+ mDelegate.unloadModel(modelHandle);
+
+ }
+
+ @Override
+ public void startRecognition(int modelHandle, @NonNull RecognitionConfig config)
+ throws RemoteException {
+ enforcePermissions();
+ mDelegate.startRecognition(modelHandle, config);
+ }
+
+ @Override
+ public void stopRecognition(int modelHandle) throws RemoteException {
+ enforcePermissions();
+ mDelegate.stopRecognition(modelHandle);
+ }
+
+ @Override
+ public void forceRecognitionEvent(int modelHandle) throws RemoteException {
+ enforcePermissions();
+ mDelegate.forceRecognitionEvent(modelHandle);
+ }
+
+ @Override
+ public void setModelParameter(int modelHandle, int modelParam, int value)
+ throws RemoteException {
+ enforcePermissions();
+ mDelegate.setModelParameter(modelHandle, modelParam, value);
+ }
+
+ @Override
+ public int getModelParameter(int modelHandle, int modelParam) throws RemoteException {
+ enforcePermissions();
+ return mDelegate.getModelParameter(modelHandle, modelParam);
+ }
+
+ @Override
+ @Nullable
+ public ModelParameterRange queryModelParameterSupport(int modelHandle, int modelParam)
+ throws RemoteException {
+ enforcePermissions();
+ return mDelegate.queryModelParameterSupport(modelHandle,
+ modelParam);
+ }
+
+ @Override
+ public void detach() throws RemoteException {
+ enforcePermissions();
+ mDelegate.detach();
+ }
+
+ // Override toString() in order to have the delegate's ID in it.
+ @Override
+ public String toString() {
+ return Objects.toString(mDelegate);
+ }
+
+ private void enforcePermissions() {
+ enforcePermissionsForPreflight(mOriginatorIdentity);
+ }
+
+ private class CallbackWrapper implements ISoundTriggerCallback {
+ private final ISoundTriggerCallback mDelegate;
+
+ private CallbackWrapper(ISoundTriggerCallback delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public void onRecognition(int modelHandle, RecognitionEvent event)
+ throws RemoteException {
+ enforcePermissions("Sound trigger recognition.");
+ mDelegate.onRecognition(modelHandle, event);
+ }
+
+ @Override
+ public void onPhraseRecognition(int modelHandle, PhraseRecognitionEvent event)
+ throws RemoteException {
+ enforcePermissions("Sound trigger phrase recognition.");
+ mDelegate.onPhraseRecognition(modelHandle, event);
+ }
+
+ @Override
+ public void onRecognitionAvailabilityChange(boolean available) throws RemoteException {
+ mDelegate.onRecognitionAvailabilityChange(available);
+ }
+
+ @Override
+ public void onModuleDied() throws RemoteException {
+ mDelegate.onModuleDied();
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mDelegate.asBinder();
+ }
+
+ // Override toString() in order to have the delegate's ID in it.
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+
+ private void enforcePermissions(String reason) {
+ enforcePermissionsForDataDelivery(mOriginatorIdentity, reason);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index 4b464d2d3e04..db7a575b08e2 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -16,9 +16,15 @@
package com.android.server.soundtrigger_middleware;
+import static android.Manifest.permission.SOUNDTRIGGER_DELEGATE_IDENTITY;
+
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.soundtrigger.V2_0.ISoundTriggerHw;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.Identity;
+import android.media.permission.PermissionUtil;
+import android.media.permission.SafeCloseable;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
@@ -62,15 +68,17 @@ import java.util.Objects;
public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareService.Stub {
static private final String TAG = "SoundTriggerMiddlewareService";
- @NonNull
- private final ISoundTriggerMiddlewareInternal mDelegate;
+ private final @NonNull ISoundTriggerMiddlewareInternal mDelegate;
+ private final @NonNull Context mContext;
/**
* Constructor for internal use only. Could be exposed for testing purposes in the future.
* Users should access this class via {@link Lifecycle}.
*/
- private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate) {
+ private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate,
+ @NonNull Context context) {
mDelegate = Objects.requireNonNull(delegate);
+ mContext = context;
new ExternalCaptureStateTracker(active -> {
try {
mDelegate.setCaptureState(active);
@@ -81,24 +89,58 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
}
@Override
- public @NonNull
- SoundTriggerModuleDescriptor[] listModules() throws RemoteException {
- return mDelegate.listModules();
+ public SoundTriggerModuleDescriptor[] listModulesAsOriginator(Identity identity) {
+ try (SafeCloseable ignored = establishIdentityDirect(identity)) {
+ return mDelegate.listModules();
+ }
}
@Override
- public @NonNull
- ISoundTriggerModule attach(int handle, @NonNull ISoundTriggerCallback callback)
- throws RemoteException {
- return new ModuleService(mDelegate.attach(handle, callback));
+ public SoundTriggerModuleDescriptor[] listModulesAsMiddleman(Identity middlemanIdentity,
+ Identity originatorIdentity) {
+ try (SafeCloseable ignored = establishIdentityIndirect(middlemanIdentity,
+ originatorIdentity)) {
+ return mDelegate.listModules();
+ }
+ }
+
+ @Override
+ public ISoundTriggerModule attachAsOriginator(int handle, Identity identity,
+ ISoundTriggerCallback callback) {
+ try (SafeCloseable ignored = establishIdentityDirect(Objects.requireNonNull(identity))) {
+ return new ModuleService(mDelegate.attach(handle, callback));
+ }
}
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ @Override
+ public ISoundTriggerModule attachAsMiddleman(int handle, Identity middlemanIdentity,
+ Identity originatorIdentity, ISoundTriggerCallback callback) {
+ try (SafeCloseable ignored = establishIdentityIndirect(
+ Objects.requireNonNull(middlemanIdentity),
+ Objects.requireNonNull(originatorIdentity))) {
+ return new ModuleService(mDelegate.attach(handle, callback));
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
if (mDelegate instanceof Dumpable) {
((Dumpable) mDelegate).dump(fout);
}
}
+ private @NonNull
+ SafeCloseable establishIdentityIndirect(Identity middlemanIdentity,
+ Identity originatorIdentity) {
+ return PermissionUtil.establishIdentityIndirect(mContext, SOUNDTRIGGER_DELEGATE_IDENTITY,
+ middlemanIdentity, originatorIdentity);
+ }
+
+ private @NonNull
+ SafeCloseable establishIdentityDirect(Identity originatorIdentity) {
+ return PermissionUtil.establishIdentityDirect(originatorIdentity);
+ }
+
private final static class ModuleService extends ISoundTriggerModule.Stub {
private final ISoundTriggerModule mDelegate;
@@ -108,55 +150,75 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
@Override
public int loadModel(SoundModel model) throws RemoteException {
- return mDelegate.loadModel(model);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return mDelegate.loadModel(model);
+ }
}
@Override
public int loadPhraseModel(PhraseSoundModel model) throws RemoteException {
- return mDelegate.loadPhraseModel(model);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return mDelegate.loadPhraseModel(model);
+ }
}
@Override
public void unloadModel(int modelHandle) throws RemoteException {
- mDelegate.unloadModel(modelHandle);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.unloadModel(modelHandle);
+ }
}
@Override
public void startRecognition(int modelHandle, RecognitionConfig config)
throws RemoteException {
- mDelegate.startRecognition(modelHandle, config);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.startRecognition(modelHandle, config);
+ }
}
@Override
public void stopRecognition(int modelHandle) throws RemoteException {
- mDelegate.stopRecognition(modelHandle);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.stopRecognition(modelHandle);
+ }
}
@Override
public void forceRecognitionEvent(int modelHandle) throws RemoteException {
- mDelegate.forceRecognitionEvent(modelHandle);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.forceRecognitionEvent(modelHandle);
+ }
}
@Override
public void setModelParameter(int modelHandle, int modelParam, int value)
throws RemoteException {
- mDelegate.setModelParameter(modelHandle, modelParam, value);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.setModelParameter(modelHandle, modelParam, value);
+ }
}
@Override
public int getModelParameter(int modelHandle, int modelParam) throws RemoteException {
- return mDelegate.getModelParameter(modelHandle, modelParam);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return mDelegate.getModelParameter(modelHandle, modelParam);
+ }
}
@Override
public ModelParameterRange queryModelParameterSupport(int modelHandle, int modelParam)
throws RemoteException {
- return mDelegate.queryModelParameterSupport(modelHandle, modelParam);
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ return mDelegate.queryModelParameterSupport(modelHandle, modelParam);
+ }
}
@Override
public void detach() throws RemoteException {
- mDelegate.detach();
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mDelegate.detach();
+ }
}
}
@@ -182,10 +244,11 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
publishBinderService(Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE,
new SoundTriggerMiddlewareService(
new SoundTriggerMiddlewareLogging(
- new SoundTriggerMiddlewareValidation(
- new SoundTriggerMiddlewareImpl(factories,
- new AudioSessionProviderImpl()),
- getContext()))));
+ new SoundTriggerMiddlewarePermission(
+ new SoundTriggerMiddlewareValidation(
+ new SoundTriggerMiddlewareImpl(factories,
+ new AudioSessionProviderImpl())),
+ getContext())), getContext()));
}
}
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 5d25d2cb554d..95a30c7f0278 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -16,11 +16,10 @@
package com.android.server.soundtrigger_middleware;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.Context;
-import android.content.PermissionChecker;
+import android.media.permission.Identity;
+import android.media.permission.IdentityContext;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
@@ -53,9 +52,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
- * This is a decorator of an {@link ISoundTriggerMiddlewareService}, which enforces permissions and
- * correct usage by the client, as well as makes sure that exceptions representing a server
- * malfunction do not get sent to the client.
+ * This is a decorator of an {@link ISoundTriggerMiddlewareService}, which enforces correct usage by
+ * the client, as well as makes sure that exceptions representing a server malfunction get sent to
+ * the client in a consistent manner, which cannot be confused with a client fault.
* <p>
* This is intended to extract the non-business logic out of the underlying implementation and thus
* make it easier to maintain each one of those separate aspects. A design trade-off is being made
@@ -70,8 +69,6 @@ import java.util.concurrent.atomic.AtomicReference;
* pattern:
* <code><pre>
* @Override public T method(S arg) {
- * // Permission check.
- * checkPermissions();
* // Input validation.
* ValidationUtil.validateS(arg);
* synchronized (this) {
@@ -95,9 +92,8 @@ import java.util.concurrent.atomic.AtomicReference;
* with client-server separation.
* <p>
* <b>Exception handling approach:</b><br>
- * We make sure all client faults (permissions, argument and state validation) happen first, and
- * would throw {@link SecurityException}, {@link IllegalArgumentException}/
- * {@link NullPointerException} or {@link
+ * We make sure all client faults (argument and state validation) happen first, and
+ * would throw {@link IllegalArgumentException}/{@link NullPointerException} or {@link
* IllegalStateException}, respectively. All those exceptions are treated specially by Binder and
* will get sent back to the client.<br>
* Once this is done, any subsequent fault is considered either a recoverable (expected) or
@@ -116,11 +112,11 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
ALIVE,
DETACHED,
DEAD
- };
+ }
private class ModuleState {
final @NonNull SoundTriggerModuleProperties properties;
- Set<ModuleService> sessions = new HashSet<>();
+ Set<Session> sessions = new HashSet<>();
private ModuleState(@NonNull SoundTriggerModuleProperties properties) {
this.properties = properties;
@@ -130,13 +126,11 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
private AtomicReference<Boolean> mCaptureState = new AtomicReference<>();
private final @NonNull ISoundTriggerMiddlewareInternal mDelegate;
- private final @NonNull Context mContext;
private Map<Integer, ModuleState> mModules;
public SoundTriggerMiddlewareValidation(
- @NonNull ISoundTriggerMiddlewareInternal delegate, @NonNull Context context) {
+ @NonNull ISoundTriggerMiddlewareInternal delegate) {
mDelegate = delegate;
- mContext = context;
}
/**
@@ -169,8 +163,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public @NonNull
SoundTriggerModuleDescriptor[] listModules() {
- // Permission check.
- checkPermissions();
// Input validation (always valid).
synchronized (this) {
@@ -179,9 +171,22 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// From here on, every exception isn't client's fault.
try {
SoundTriggerModuleDescriptor[] result = mDelegate.listModules();
- mModules = new HashMap<>(result.length);
- for (SoundTriggerModuleDescriptor desc : result) {
- mModules.put(desc.handle, new ModuleState(desc.properties));
+ if (mModules == null) {
+ mModules = new HashMap<>(result.length);
+ for (SoundTriggerModuleDescriptor desc : result) {
+ mModules.put(desc.handle, new ModuleState(desc.properties));
+ }
+ } else {
+ if (result.length != mModules.size()) {
+ throw new RuntimeException(
+ "listModules must always return the same result.");
+ }
+ for (SoundTriggerModuleDescriptor desc : result) {
+ if (!mModules.containsKey(desc.handle)) {
+ throw new RuntimeException(
+ "listModules must always return the same result.");
+ }
+ }
}
return result;
} catch (Exception e) {
@@ -193,8 +198,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public @NonNull ISoundTriggerModule attach(int handle,
@NonNull ISoundTriggerCallback callback) {
- // Permission check.
- checkPermissions();
// Input validation.
Objects.requireNonNull(callback);
Objects.requireNonNull(callback.asBinder());
@@ -211,10 +214,9 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// From here on, every exception isn't client's fault.
try {
- ModuleService moduleService =
- new ModuleService(handle, callback);
- moduleService.attach(mDelegate.attach(handle, moduleService));
- return moduleService;
+ Session session = new Session(handle, callback);
+ session.attach(mDelegate.attach(handle, session.getCallbackWrapper()));
+ return session;
} catch (Exception e) {
throw handleException(e);
}
@@ -244,40 +246,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
return mDelegate.toString();
}
- /**
- * Throws a {@link SecurityException} if caller permanently doesn't have the given permission,
- * or a {@link ServiceSpecificException} with a {@link Status#TEMPORARY_PERMISSION_DENIED} if
- * caller temporarily doesn't have the right permissions to use this service.
- */
- void checkPermissions() {
- enforcePermission(Manifest.permission.RECORD_AUDIO);
- enforcePermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD);
- }
-
- /**
- * Throws a {@link SecurityException} if caller permanently doesn't have the given permission,
- * or a {@link ServiceSpecificException} with a {@link Status#TEMPORARY_PERMISSION_DENIED} if
- * caller temporarily doesn't have the given permission.
- *
- * @param permission The permission to check.
- */
- void enforcePermission(String permission) {
- final int status = PermissionChecker.checkCallingOrSelfPermissionForPreflight(mContext,
- permission);
- switch (status) {
- case PermissionChecker.PERMISSION_GRANTED:
- return;
- case PermissionChecker.PERMISSION_HARD_DENIED:
- throw new SecurityException(
- String.format("Caller must have the %s permission.", permission));
- case PermissionChecker.PERMISSION_SOFT_DENIED:
- throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED,
- String.format("Caller must have the %s permission.", permission));
- default:
- throw new RuntimeException("Unexpected perimission check result.");
- }
- }
-
@Override
public IBinder asBinder() {
throw new UnsupportedOperationException(
@@ -297,7 +265,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
pw.printf("Module %d\n%s\n", handle,
ObjectPrinter.print(module.properties, true, 16));
pw.println("=========================================");
- for (ModuleService session : module.sessions) {
+ for (Session session : module.sessions) {
session.dump(pw);
}
}
@@ -327,7 +295,14 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
/** Model is loaded, recognition is inactive. */
LOADED,
/** Model is loaded, recognition is active. */
- ACTIVE
+ ACTIVE,
+ /**
+ * Model is active as far as the client is concerned, but loaded as far as the
+ * layers are concerned. This condition occurs when a recognition event that indicates
+ * the recognition for this model arrived from the underlying layer, but had not been
+ * delivered to the caller (most commonly, for permission reasons).
+ */
+ INTERCEPTED,
}
/** Activity state. */
@@ -400,9 +375,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
* A wrapper around an {@link ISoundTriggerModule} implementation, to address the same aspects
* mentioned in {@link SoundTriggerModule} above. This class follows the same conventions.
*/
- private class ModuleService extends ISoundTriggerModule.Stub implements ISoundTriggerCallback,
- IBinder.DeathRecipient {
- private final ISoundTriggerCallback mCallback;
+ private class Session extends ISoundTriggerModule.Stub {
private ISoundTriggerModule mDelegate;
// While generally all the fields of this class must be changed under a lock, an exception
// is made for the specific case of changing a model state from ACTIVE to LOADED, which
@@ -413,15 +386,17 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
ConcurrentMap<Integer, ModelState> mLoadedModels = new ConcurrentHashMap<>();
private final int mHandle;
private ModuleStatus mState = ModuleStatus.ALIVE;
+ private final CallbackWrapper mCallbackWrapper;
+ private final Identity mOriginatorIdentity;
- ModuleService(int handle, @NonNull ISoundTriggerCallback callback) {
- mCallback = callback;
+ Session(int handle, @NonNull ISoundTriggerCallback callback) {
+ mCallbackWrapper = new CallbackWrapper(callback);
mHandle = handle;
- try {
- mCallback.asBinder().linkToDeath(this, 0);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
+ mOriginatorIdentity = IdentityContext.get();
+ }
+
+ ISoundTriggerCallback getCallbackWrapper() {
+ return mCallbackWrapper;
}
void attach(@NonNull ISoundTriggerModule delegate) {
@@ -431,8 +406,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public int loadModel(@NonNull SoundModel model) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validateGenericModel(model);
@@ -455,8 +428,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public int loadPhraseModel(@NonNull PhraseSoundModel model) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validatePhraseModel(model);
@@ -479,8 +450,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void unloadModel(int modelHandle) {
- // Permission check.
- checkPermissions();
// Input validation (always valid).
synchronized (SoundTriggerMiddlewareValidation.this) {
@@ -495,7 +464,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
}
if (modelState.getActivityState() != ModelState.Activity.LOADED) {
throw new IllegalStateException("Model with handle: " + modelHandle
- + " has invalid state for unloading: " + modelState.getActivityState());
+ + " has invalid state for unloading");
}
// From here on, every exception isn't client's fault.
@@ -510,8 +479,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void startRecognition(int modelHandle, @NonNull RecognitionConfig config) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validateRecognitionConfig(config);
@@ -527,8 +494,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
}
if (modelState.getActivityState() != ModelState.Activity.LOADED) {
throw new IllegalStateException("Model with handle: " + modelHandle
- + " has invalid state for starting recognition: "
- + modelState.getActivityState());
+ + " has invalid state for starting recognition");
}
// From here on, every exception isn't client's fault.
@@ -547,8 +513,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void stopRecognition(int modelHandle) {
- // Permission check.
- checkPermissions();
// Input validation (always valid).
synchronized (SoundTriggerMiddlewareValidation.this) {
@@ -565,7 +529,12 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// From here on, every exception isn't client's fault.
try {
- mDelegate.stopRecognition(modelHandle);
+ // If the activity state is LOADED or INTERCEPTED, we skip delegating the
+ // command, but still consider the call valid. In either case, the resulting
+ // state is LOADED.
+ if (modelState.getActivityState() == ModelState.Activity.ACTIVE) {
+ mDelegate.stopRecognition(modelHandle);
+ }
modelState.setActivityState(ModelState.Activity.LOADED);
} catch (Exception e) {
throw handleException(e);
@@ -575,8 +544,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void forceRecognitionEvent(int modelHandle) {
- // Permission check.
- checkPermissions();
// Input validation (always valid).
synchronized (SoundTriggerMiddlewareValidation.this) {
@@ -593,7 +560,11 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// From here on, every exception isn't client's fault.
try {
- mDelegate.forceRecognitionEvent(modelHandle);
+ // If the activity state is LOADED or INTERCEPTED, we skip delegating the
+ // command, but still consider the call valid.
+ if (modelState.getActivityState() == ModelState.Activity.ACTIVE) {
+ mDelegate.forceRecognitionEvent(modelHandle);
+ }
} catch (Exception e) {
throw handleException(e);
}
@@ -602,8 +573,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void setModelParameter(int modelHandle, int modelParam, int value) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validateModelParameter(modelParam);
@@ -630,8 +599,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public int getModelParameter(int modelHandle, int modelParam) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validateModelParameter(modelParam);
@@ -659,8 +626,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
@Nullable
public ModelParameterRange queryModelParameterSupport(int modelHandle, int modelParam) {
- // Permission check.
- checkPermissions();
// Input validation.
ValidationUtil.validateModelParameter(modelParam);
@@ -689,8 +654,6 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
@Override
public void detach() {
- // Permission check.
- checkPermissions();
// Input validation (always valid).
synchronized (SoundTriggerMiddlewareValidation.this) {
@@ -714,14 +677,14 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// Override toString() in order to have the delegate's ID in it.
@Override
public String toString() {
- return Objects.toString(mDelegate.toString());
+ return Objects.toString(mDelegate);
}
private void detachInternal() {
try {
mDelegate.detach();
mState = ModuleStatus.DETACHED;
- mCallback.asBinder().unlinkToDeath(this, 0);
+ mCallbackWrapper.detached();
mModules.get(mHandle).sessions.remove(this);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
@@ -730,7 +693,10 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
void dump(PrintWriter pw) {
if (mState == ModuleStatus.ALIVE) {
- pw.printf("Loaded models for session %s (handle, active)", toString());
+ pw.println("-------------------------------");
+ pw.printf("Session %s, client: %s\n", toString(),
+ ObjectPrinter.print(mOriginatorIdentity, true, 16));
+ pw.printf("Loaded models (handle, active, description):", toString());
pw.println();
pw.println("-------------------------------");
for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
@@ -741,16 +707,31 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
pw.print(entry.getValue().description);
pw.println();
}
+ pw.println();
} else {
pw.printf("Session %s is dead", toString());
pw.println();
}
}
- ////////////////////////////////////////////////////////////////////////////////////////////
- // Callbacks
+ class CallbackWrapper implements ISoundTriggerCallback,
+ IBinder.DeathRecipient {
+ private final ISoundTriggerCallback mCallback;
- @Override
+ CallbackWrapper(ISoundTriggerCallback callback) {
+ mCallback = callback;
+ try {
+ mCallback.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ void detached() {
+ mCallback.asBinder().unlinkToDeath(this, 0);
+ }
+
+ @Override
public void onRecognition(int modelHandle, @NonNull RecognitionEvent event) {
// We cannot obtain a lock on SoundTriggerMiddlewareValidation.this, since this call
// might be coming from the audio server (via setCaptureState()) while it is holding
@@ -759,18 +740,21 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// To avoid this problem, we use an atomic model activity state. There is a risk of the
// model not being in the mLoadedModels map here, since it might have been stopped /
// unloaded while the event was in flight.
- if (event.status != RecognitionStatus.FORCED) {
- ModelState modelState = mLoadedModels.get(modelHandle);
- if (modelState != null) {
+ ModelState modelState = mLoadedModels.get(modelHandle);
+ if (modelState != null) {
+ if (event.status != RecognitionStatus.FORCED) {
modelState.setActivityState(ModelState.Activity.LOADED);
}
- }
- try {
- mCallback.onRecognition(modelHandle, event);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
+ try {
+ mCallback.onRecognition(modelHandle, event);
+ } catch (Exception e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
+ if (event.status != RecognitionStatus.FORCED) {
+ modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+ }
+ }
}
}
@@ -783,18 +767,21 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// To avoid this problem, we use an atomic model activity state. There is a risk of the
// model not being in the mLoadedModels map here, since it might have been stopped /
// unloaded while the event was in flight.
- if (event.common.status != RecognitionStatus.FORCED) {
- ModelState modelState = mLoadedModels.get(modelHandle);
- if (modelState != null) {
- modelState.setActivityState(ModelState.Activity.LOADED);
+ ModelState modelState = mLoadedModels.get(modelHandle);
+ if (modelState != null) {
+ if (event.common.status != RecognitionStatus.FORCED) {
+ modelState.setActivityState(ModelState.Activity.LOADED);
+ }
+ try {
+ mCallback.onPhraseRecognition(modelHandle, event);
+ } catch (Exception e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
+ if (event.common.status != RecognitionStatus.FORCED) {
+ modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+ }
}
- }
- try {
- mCallback.onPhraseRecognition(modelHandle, event);
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
}
}
@@ -810,41 +797,53 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
}
}
- @Override
- public void onModuleDied() {
- synchronized (SoundTriggerMiddlewareValidation.this) {
- mState = ModuleStatus.DEAD;
- }
- // Trigger the callback outside of the lock to avoid deadlocks.
- try {
- mCallback.onModuleDied();
- } catch (RemoteException e) {
- // Dead client will be handled by binderDied() - no need to handle here.
- // In any case, client callbacks are considered best effort.
- Log.e(TAG, "Client callback exception.", e);
+ @Override
+ public void onModuleDied() {
+ synchronized (SoundTriggerMiddlewareValidation.this) {
+ mState = ModuleStatus.DEAD;
+ }
+ // Trigger the callback outside of the lock to avoid deadlocks.
+ try {
+ mCallback.onModuleDied();
+ } catch (RemoteException e) {
+ // Dead client will be handled by binderDied() - no need to handle here.
+ // In any case, client callbacks are considered best effort.
+ Log.e(TAG, "Client callback exception.", e);
+ }
}
- }
-
- @Override
- public void binderDied() {
- // This is called whenever our client process dies.
- synchronized (SoundTriggerMiddlewareValidation.this) {
- try {
- // Gracefully stop all active recognitions and unload the models.
- for (Map.Entry<Integer, ModelState> entry :
- mLoadedModels.entrySet()) {
- // Idempotent call, no harm in calling even for models that are already
- // stopped.
- mDelegate.stopRecognition(entry.getKey());
- mDelegate.unloadModel(entry.getKey());
+ @Override
+ public void binderDied() {
+ // This is called whenever our client process dies.
+ synchronized (SoundTriggerMiddlewareValidation.this) {
+ try {
+ // Gracefully stop all active recognitions and unload the models.
+ for (Map.Entry<Integer, ModelState> entry :
+ mLoadedModels.entrySet()) {
+ if (entry.getValue().getActivityState()
+ == ModelState.Activity.ACTIVE) {
+ mDelegate.stopRecognition(entry.getKey());
+ }
+ mDelegate.unloadModel(entry.getKey());
+ }
+ // Detach.
+ detachInternal();
+ } catch (Exception e) {
+ throw handleException(e);
}
- // Detach.
- detachInternal();
- } catch (Exception e) {
- throw handleException(e);
}
}
+
+ @Override
+ public IBinder asBinder() {
+ return mCallback.asBinder();
+ }
+
+ // Override toString() in order to have the delegate's ID in it.
+ @Override
+ public String toString() {
+ return Objects.toString(mDelegate);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
index 5a587cc9764c..02d978dfdf99 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
@@ -184,11 +184,13 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
@Override
public void serviceDied(long cookie) {
Log.w(TAG, String.format("Underlying HAL driver died."));
- List<ISoundTriggerCallback> callbacks = new ArrayList<>(mActiveSessions.size());
+ List<ISoundTriggerCallback> callbacks;
synchronized (this) {
+ callbacks = new ArrayList<>(mActiveSessions.size());
for (Session session : mActiveSessions) {
callbacks.add(session.moduleDied());
}
+ mActiveSessions.clear();
reset();
}
// Trigger the callbacks outside of the lock to avoid deadlocks.
@@ -431,7 +433,6 @@ class SoundTriggerModule implements IHwBinder.DeathRecipient {
*/
private ISoundTriggerCallback moduleDied() {
ISoundTriggerCallback callback = mCallback;
- removeSession(this);
mCallback = null;
return callback;
}
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 3e638502db56..740b592fda4c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2606,7 +2606,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
}
stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
- null /* resuming */);
+ null /* resuming */, "finish");
}
if (endTask) {
@@ -4770,14 +4770,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
supportsEnterPipOnTaskSwitch = false;
break;
case RESUMED:
- // If the app is capable of entering PIP, we should try pausing it now
- // so it can PIP correctly.
- if (deferHidingClient) {
- getRootTask().startPausingLocked(
- mStackSupervisor.mUserLeaving /* userLeaving */,
- false /* uiSleeping */, null /* resuming */);
+ // Do nothing if currently in the process of resuming the activity. Otherwise,
+ // starting to pause it since it is not visible.
+ if (!mSetToSleep) {
break;
}
+ getRootTask().startPausingLocked(mStackSupervisor.mUserLeaving,
+ false /* uiSleeping */, null /* resuming */, "makeInvisible");
+ // fall through
case INITIALIZING:
case PAUSING:
case PAUSED:
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ebfd0cd9fd83..15669cbe227a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -123,7 +123,6 @@ import static com.android.server.wm.Task.ActivityState.DESTROYED;
import static com.android.server.wm.Task.ActivityState.DESTROYING;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT;
-import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
@@ -3952,52 +3951,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- /**
- * Try to place task to provided position. The final position might be different depending on
- * current user and stacks state. The task will be moved to target stack if it's currently in
- * different stack.
- */
- @Override
- public void positionTaskInStack(int taskId, int stackId, int position) {
- mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
- synchronized (mGlobalLock) {
- long ident = Binder.clearCallingIdentity();
- try {
- if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task="
- + taskId + " in stackId=" + stackId + " at position=" + position);
- final Task task = mRootWindowContainer.anyTaskForId(taskId);
- if (task == null) {
- throw new IllegalArgumentException("positionTaskInStack: no task for id="
- + taskId);
- }
-
- final Task stack = mRootWindowContainer.getStack(stackId);
-
- if (stack == null) {
- throw new IllegalArgumentException("positionTaskInStack: no stack for id="
- + stackId);
- }
- if (!stack.isActivityTypeStandardOrUndefined()) {
- throw new IllegalArgumentException("positionTaskInStack: Attempt to change"
- + " the position of task " + taskId + " in/to non-standard stack");
- }
-
- // TODO: Have the callers of this API call a separate reparent method if that is
- // what they intended to do vs. having this method also do reparenting.
- if (task.getRootTask() == stack) {
- // Change position in current stack.
- stack.positionChildAt(task, position);
- } else {
- // Reparent to new stack.
- task.reparent(stack, position, REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
- !DEFER_RESUME, "positionTaskInStack");
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
@Override
public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration,
int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0044d7498614..0be5cbe5199c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -28,6 +28,8 @@ 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_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
@@ -464,6 +466,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
ActivityRecord mFocusedApp = null;
+ /** The last focused {@link TaskDisplayArea} on this display. */
+ private TaskDisplayArea mLastFocusedTaskDisplayArea = null;
+
/**
* The launching activity which is using fixed rotation transformation.
*
@@ -2327,7 +2332,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return getLastOrientation();
}
}
- return super.getOrientation();
+
+ final int orientation = super.getOrientation();
+ if (orientation != SCREEN_ORIENTATION_UNSET && orientation != SCREEN_ORIENTATION_BEHIND) {
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "App is requesting an orientation, return %d for display id=%d",
+ orientation, mDisplayId);
+ return orientation;
+ }
+
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "No app is requesting an orientation, return %d for display id=%d",
+ getLastOrientation(), mDisplayId);
+ // The next app has not been requested to be visible, so we keep the current orientation
+ // to prevent freezing/unfreezing the display too early.
+ return getLastOrientation();
}
void updateDisplayInfo() {
@@ -3202,6 +3221,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
throw new IllegalStateException(newFocus + " is not on " + getName()
+ " but " + ((appDisplay != null) ? appDisplay.getName() : "none"));
}
+
+ // Called even if the focused app is not changed in case the app is moved to a different
+ // TaskDisplayArea.
+ setLastFocusedTaskDisplayArea(newFocus.getDisplayArea());
}
if (mFocusedApp == newFocus) {
return false;
@@ -3214,6 +3237,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return true;
}
+ /** Called when the focused {@link TaskDisplayArea} on this display may have changed. */
+ @VisibleForTesting
+ void setLastFocusedTaskDisplayArea(@Nullable TaskDisplayArea taskDisplayArea) {
+ if (taskDisplayArea != null) {
+ mLastFocusedTaskDisplayArea = taskDisplayArea;
+ }
+ }
+
+ /** Gets the last focused {@link TaskDisplayArea} on this display. */
+ TaskDisplayArea getLastFocusedTaskDisplayArea() {
+ return mLastFocusedTaskDisplayArea;
+ }
+
/** Updates the layer assignment of windows on this display. */
void assignWindowLayers(boolean setLayoutNeeded) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index aab901ebcdb6..6c346090578f 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -26,7 +26,7 @@ option java_package com.android.server.wm
# The Activity Manager failed to pause the given activity.
30012 wm_failed_to_pause (User|1|5),(Token|1|5),(Wanting to pause|3),(Currently pausing|3)
# Attempting to pause the current activity
-30013 wm_pause_activity (User|1|5),(Token|1|5),(Component Name|3),(User Leaving|3)
+30013 wm_pause_activity (User|1|5),(Token|1|5),(Component Name|3),(User Leaving|3),(Reason|3)
# Application process has been started
# An activity is being destroyed:
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 18a25033b1e6..361788497e11 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -36,12 +36,12 @@ import android.view.InsetsAnimationControlCallbacks;
import android.view.InsetsAnimationControlImpl;
import android.view.InsetsAnimationControlRunner;
import android.view.InsetsController;
+import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
-import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowInsetsAnimationControlListener;
@@ -139,9 +139,6 @@ class InsetsPolicy {
getFakeControlTarget(focusedWin, statusControlTarget),
navControlTarget,
getFakeControlTarget(focusedWin, navControlTarget));
- if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
- return;
- }
mStatusBar.updateVisibility(statusControlTarget, ITYPE_STATUS_BAR);
mNavBar.updateVisibility(navControlTarget, ITYPE_NAVIGATION_BAR);
mPolicy.updateHideNavInputEventReceiver();
@@ -211,11 +208,21 @@ class InsetsPolicy {
* @see InsetsStateController#getInsetsForDispatch
*/
InsetsState getInsetsForDispatch(WindowState target) {
- InsetsState originalState = mStateController.getInsetsForDispatch(target);
+ final InsetsState originalState = mStateController.getInsetsForDispatch(target);
InsetsState state = originalState;
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- state = new InsetsState(state);
- state.setSourceVisible(mShowingTransientTypes.get(i), false);
+ final int type = mShowingTransientTypes.get(i);
+ final InsetsSource originalSource = state.peekSource(type);
+ if (originalSource != null && originalSource.isVisible()) {
+ if (state == originalState) {
+ // The source will be modified, create a non-deep copy to store the new one.
+ state = new InsetsState(originalState);
+ }
+ // Replace the source with a copy in invisible state.
+ final InsetsSource source = new InsetsSource(originalSource);
+ source.setVisible(false);
+ state.addSource(source);
+ }
}
return state;
}
@@ -251,11 +258,14 @@ class InsetsPolicy {
}
}
+ /**
+ * If the caller is not {@link #updateBarControlTarget}, it should call
+ * updateBarControlTarget(mFocusedWin) after this invocation.
+ */
private void abortTransient() {
mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
mShowingTransientTypes.toArray());
mShowingTransientTypes.clear();
- updateBarControlTarget(mFocusedWin);
}
private @Nullable InsetsControlTarget getFakeControlTarget(@Nullable WindowState focused,
@@ -289,7 +299,7 @@ class InsetsPolicy {
// fake control to the client, so that it can re-show the bar during this scenario.
return mDummyControlTarget;
}
- if (mPolicy.topAppHidesStatusBar()) {
+ if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar()) {
// Non-fullscreen focused window should not break the state that the top-fullscreen-app
// window hides status bar.
return mPolicy.getTopFullscreenOpaqueWindow();
@@ -297,6 +307,16 @@ class InsetsPolicy {
return focusedWin;
}
+ private static boolean canBeTopFullscreenOpaqueWindow(@Nullable WindowState win) {
+ // The condition doesn't use WindowState#canAffectSystemUiFlags because the window may
+ // haven't drawn or committed the visibility.
+ final boolean nonAttachedAppWindow = win != null
+ && win.mAttrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && win.mAttrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+ return nonAttachedAppWindow && win.mAttrs.isFullscreen() && !win.isFullyTransparent()
+ && !win.inMultiWindowMode();
+ }
+
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
boolean forceShowsSystemBarsForWindowingMode) {
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index e00c9e7ac38b..a7f32c09b83b 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -19,10 +19,6 @@ package com.android.server.wm;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL;
@@ -93,13 +89,14 @@ class InsetsSourceProvider {
mFakeControl = new InsetsSourceControl(source.getType(), null /* leash */,
new Point());
- final int type = source.getType();
- if (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR) {
- mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
- } else if (type == ITYPE_IME) {
- mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
- } else {
- mControllable = false;
+ switch (source.getType()) {
+ case ITYPE_STATUS_BAR:
+ case ITYPE_NAVIGATION_BAR:
+ case ITYPE_IME:
+ mControllable = true;
+ break;
+ default:
+ mControllable = false;
}
}
@@ -395,7 +392,7 @@ class InsetsSourceProvider {
}
boolean isClientVisible() {
- return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
+ return mClientVisible;
}
/**
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 5520ad37e8ed..c0bdbff6b761 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -24,8 +24,6 @@ import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -382,9 +380,6 @@ class InsetsStateController {
*/
void onControlFakeTargetChanged(@InternalInsetsType int type,
@Nullable InsetsControlTarget fakeTarget) {
- if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
- return;
- }
final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type);
if (fakeTarget == previous) {
return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b7a5d05486c4..2a0488d6e230 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1102,7 +1102,7 @@ class Task extends WindowContainer<WindowContainer> {
&& toStack.topRunningActivity() != null) {
// Pause the resumed activity on the target stack while re-parenting task on top of it.
toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
- null /* resuming */);
+ null /* resuming */, "reparent");
}
final int toStackWindowingMode = toStack.getWindowingMode();
@@ -5340,7 +5340,8 @@ class Task extends WindowContainer<WindowContainer> {
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"Sleep => pause with userLeaving=false");
- startPausingLocked(false /* userLeaving */, true /* uiSleeping */, null /* resuming */);
+ startPausingLocked(false /* userLeaving */, true /* uiSleeping */, null /* resuming */,
+ "sleep");
shouldSleep = false ;
} else if (mPausingActivity != null) {
// Still waiting for something to pause; can't sleep yet.
@@ -5400,11 +5401,12 @@ class Task extends WindowContainer<WindowContainer> {
* @param resuming The activity we are currently trying to resume or null if this is not being
* called as part of resuming the top activity, so we shouldn't try to instigate
* a resume here if not null.
+ * @param reason The reason of pausing the activity.
* @return Returns true if an activity now is in the PAUSING state, and we are waiting for
* it to tell us when it is done.
*/
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
- ActivityRecord resuming) {
+ ActivityRecord resuming, String reason) {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
@@ -5471,7 +5473,7 @@ class Task extends WindowContainer<WindowContainer> {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
- prev.shortComponentName, "userLeaving=" + userLeaving);
+ prev.shortComponentName, "userLeaving=" + userLeaving, reason);
mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
@@ -5995,7 +5997,8 @@ class Task extends WindowContainer<WindowContainer> {
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
- pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
+ pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next,
+ "resumeTopActivityInnerLocked");
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 890f56e50bac..c11624c92117 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -29,12 +29,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
@@ -645,6 +643,12 @@ final class TaskDisplayArea extends DisplayArea<Task> {
@Override
int getOrientation(int candidate) {
+ // Only allow to specify orientation if this TDA has the focus.
+ // TODO(b/155431879) Add option to never allow a TDA to specify orientation.
+ if (!isLastFocused()) {
+ return SCREEN_ORIENTATION_UNSET;
+ }
+
if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
// Apps and their containers are not allowed to specify an orientation while using
// root tasks...except for the home stack if it is not resizable and currently
@@ -671,21 +675,7 @@ final class TaskDisplayArea extends DisplayArea<Task> {
return SCREEN_ORIENTATION_UNSPECIFIED;
}
- final int orientation = super.getOrientation(candidate);
- if (orientation != SCREEN_ORIENTATION_UNSET
- && orientation != SCREEN_ORIENTATION_BEHIND) {
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "App is requesting an orientation, return %d for display id=%d",
- orientation, mDisplayContent.mDisplayId);
- return orientation;
- }
-
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "No app is requesting an orientation, return %d for display id=%d",
- mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
- // The next app has not been requested to be visible, so we keep the current orientation
- // to prevent freezing/unfreezing the display too early.
- return mDisplayContent.getLastOrientation();
+ return super.getOrientation(candidate);
}
@Override
@@ -1219,7 +1209,7 @@ final class TaskDisplayArea extends DisplayArea<Task> {
+ " mResumedActivity=" + resumedActivity);
}
someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
- resuming);
+ resuming, "pauseBackStacks");
}
}
return someActivityPaused;
@@ -1880,6 +1870,12 @@ final class TaskDisplayArea extends DisplayArea<Task> {
return lastReparentedStack;
}
+ /** Whether this task display area is the last focused one on this logical display. */
+ @VisibleForTesting
+ boolean isLastFocused() {
+ return mDisplayContent.getLastFocusedTaskDisplayArea() == this;
+ }
+
@Override
protected boolean isTaskDisplayArea() {
return true;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f39fa1b7fbc8..bc4f75276a95 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -481,13 +481,11 @@ class TaskSnapshotController {
final int color = ColorUtils.setAlphaComponent(
task.getTaskDescription().getBackgroundColor(), 255);
final LayoutParams attrs = mainWindow.getAttrs();
- final InsetsPolicy insetsPolicy = mainWindow.getDisplayContent().getInsetsPolicy();
- final InsetsState insetsState =
- new InsetsState(insetsPolicy.getInsetsForDispatch(mainWindow));
+ final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState());
mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState());
final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
- attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
+ attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
mHighResTaskSnapshotScale, insetsState);
final int taskWidth = task.getBounds().width();
final int taskHeight = task.getBounds().height();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 100f1bff12a7..cccda3a4f4b8 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -19,8 +19,8 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.graphics.Color.WHITE;
import static android.graphics.Color.alpha;
-import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
-import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
@@ -75,7 +75,6 @@ import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
-import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.window.ClientWindowFrames;
@@ -167,7 +166,7 @@ class TaskSnapshotSurface implements StartingSurface {
final TaskDescription taskDescription = new TaskDescription();
taskDescription.setBackgroundColor(WHITE);
final WindowState topFullscreenOpaqueWindow;
- final int sysUiVis;
+ final int appearance;
final int windowFlags;
final int windowPrivateFlags;
final int currentOrientation;
@@ -204,8 +203,8 @@ class TaskSnapshotSurface implements StartingSurface {
topFullscreenActivity, false /* checkOpening */);
}
- sysUiVis = topFullscreenOpaqueWindow.getSystemUiVisibility();
WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
+ appearance = attrs.insetsFlags.appearance;
windowFlags = attrs.flags;
windowPrivateFlags = attrs.privateFlags;
@@ -221,11 +220,8 @@ class TaskSnapshotSurface implements StartingSurface {
layoutParams.token = activity.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
- layoutParams.systemUiVisibility = sysUiVis;
- layoutParams.insetsFlags.behavior
- = topFullscreenOpaqueWindow.mAttrs.insetsFlags.behavior;
- layoutParams.insetsFlags.appearance
- = topFullscreenOpaqueWindow.mAttrs.insetsFlags.appearance;
+ layoutParams.insetsFlags.appearance = appearance;
+ layoutParams.insetsFlags.behavior = attrs.insetsFlags.behavior;
layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
@@ -241,11 +237,7 @@ class TaskSnapshotSurface implements StartingSurface {
task.getBounds(taskBounds);
currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
activityType = activity.getActivityType();
-
- final InsetsPolicy insetsPolicy = topFullscreenOpaqueWindow.getDisplayContent()
- .getInsetsPolicy();
- insetsState =
- new InsetsState(insetsPolicy.getInsetsForDispatch(topFullscreenOpaqueWindow));
+ insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState());
mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState());
}
try {
@@ -261,7 +253,7 @@ class TaskSnapshotSurface implements StartingSurface {
// Local call.
}
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
- surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
+ surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance,
windowFlags, windowPrivateFlags, taskBounds, currentOrientation, activityType,
insetsState);
window.setOuter(snapshotSurface);
@@ -282,7 +274,7 @@ class TaskSnapshotSurface implements StartingSurface {
@VisibleForTesting
TaskSnapshotSurface(WindowManagerService service, Window window, SurfaceControl surfaceControl,
TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
- int sysUiVis, int windowFlags, int windowPrivateFlags, Rect taskBounds,
+ int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds,
int currentOrientation, int activityType, InsetsState insetsState) {
mService = service;
mSurface = service.mSurfaceFactory.get();
@@ -296,7 +288,7 @@ class TaskSnapshotSurface implements StartingSurface {
mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
mTaskBounds = taskBounds;
mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
- windowPrivateFlags, sysUiVis, taskDescription, 1f, insetsState);
+ windowPrivateFlags, appearance, taskDescription, 1f, insetsState);
mStatusBarColor = taskDescription.getStatusBarColor();
mOrientationOnCreation = currentOrientation;
mActivityType = activityType;
@@ -554,28 +546,26 @@ class TaskSnapshotSurface implements StartingSurface {
private final int mNavigationBarColor;
private final int mWindowFlags;
private final int mWindowPrivateFlags;
- private final int mSysUiVis;
private final float mScale;
private final InsetsState mInsetsState;
private final Rect mSystemBarInsets = new Rect();
- SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
+ SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
TaskDescription taskDescription, float scale, InsetsState insetsState) {
mWindowFlags = windowFlags;
mWindowPrivateFlags = windowPrivateFlags;
- mSysUiVis = sysUiVis;
mScale = scale;
final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
final int semiTransparent = context.getColor(
R.color.system_bar_background_semi_transparent);
mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
- semiTransparent, taskDescription.getStatusBarColor(), sysUiVis,
- SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ semiTransparent, taskDescription.getStatusBarColor(), appearance,
+ APPEARANCE_LIGHT_STATUS_BARS,
taskDescription.getEnsureStatusBarContrastWhenTransparent());
mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
- taskDescription.getNavigationBarColor(), sysUiVis,
- SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ taskDescription.getNavigationBarColor(), appearance,
+ APPEARANCE_LIGHT_NAVIGATION_BARS,
taskDescription.getEnsureNavigationBarContrastWhenTransparent()
&& context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
mStatusBarPaint.setColor(mStatusBarColor);
@@ -590,11 +580,8 @@ class TaskSnapshotSurface implements StartingSurface {
int getStatusBarColorViewHeight() {
final boolean forceBarBackground =
(mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
- ? STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
- : STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
return (int) (mSystemBarInsets.top * mScale);
} else {
return 0;
@@ -604,11 +591,8 @@ class TaskSnapshotSurface implements StartingSurface {
private boolean isNavigationBarColorViewVisible() {
final boolean forceBarBackground =
(mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- return ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
- ? NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mNavigationBarColor, mWindowFlags, forceBarBackground)
- : NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
}
void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 8bf0820c7dad..67d230aae0fb 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -768,7 +768,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
final Task stack = mPreQTopResumedActivity.getRootTask();
if (stack != null) {
stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
- activity);
+ activity, "top-resumed-changed");
}
}
mPreQTopResumedActivity = activity;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f2f3cefae8a5..e4a079d84a2a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1531,6 +1531,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return getDisplayContent().getDisplayInfo();
}
+ /**
+ * Returns the insets state for the client. Its sources may be the copies with visibility
+ * modification according to the state of transient bars.
+ */
InsetsState getInsetsState() {
return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
}
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 9e2bb45ab341..631e185fffce 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -225,6 +225,20 @@ std::optional<T> read(IncFsSpan& data) {
return res;
}
+static inline unique_fd openLocalFile(JNIEnv* env, const JniIds& jni, jobject shellCommand,
+ const std::string& path) {
+ if (shellCommand) {
+ return unique_fd{env->CallStaticIntMethod(jni.packageManagerShellCommandDataLoader,
+ jni.pmscdGetLocalFile, shellCommand,
+ env->NewStringUTF(path.c_str()))};
+ }
+ auto fd = unique_fd(::open(path.c_str(), O_RDONLY | O_CLOEXEC));
+ if (!fd.ok()) {
+ PLOG(ERROR) << "Failed to open file: " << path << ", error code: " << fd.get();
+ }
+ return fd;
+}
+
static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject shellCommand,
IncFsSize size, const std::string& filePath) {
InputDescs result;
@@ -232,9 +246,7 @@ static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject s
const std::string idsigPath = filePath + ".idsig";
- unique_fd idsigFd{env->CallStaticIntMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetLocalFile, shellCommand,
- env->NewStringUTF(idsigPath.c_str()))};
+ unique_fd idsigFd = openLocalFile(env, jni, shellCommand, idsigPath);
if (idsigFd.ok()) {
auto treeSize = verityTreeSizeForFile(size);
auto actualTreeSize = skipIdSigHeaders(idsigFd);
@@ -250,9 +262,7 @@ static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject s
});
}
- unique_fd fileFd{env->CallStaticIntMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetLocalFile, shellCommand,
- env->NewStringUTF(filePath.c_str()))};
+ unique_fd fileFd = openLocalFile(env, jni, shellCommand, filePath);
if (fileFd.ok()) {
result.push_back(InputDesc{
.fd = std::move(fileFd),
@@ -272,6 +282,11 @@ static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shel
std::string(metadata.data, metadata.size));
}
+ if (!shellCommand) {
+ ALOGE("Missing shell command.");
+ return {};
+ }
+
unique_fd fd{env->CallStaticIntMethod(jni.packageManagerShellCommandDataLoader,
jni.pmscdGetStdIn, shellCommand)};
if (!fd.ok()) {
@@ -396,10 +411,6 @@ private:
jobject shellCommand = env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
jni.pmscdLookupShellCommand,
env->NewStringUTF(mArgs.c_str()));
- if (!shellCommand) {
- ALOGE("Missing shell command.");
- return false;
- }
std::vector<char> buffer;
buffer.reserve(BUFFER_SIZE);
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index bf3a8964465b..2f8825b064ce 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -200,16 +200,24 @@ static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
return {0, id, nfp};
}
+static std::span<const uint8_t> toSpan(const ::std::optional<::std::vector<uint8_t>>& content) {
+ if (!content) {
+ return {};
+ }
+ return {content->data(), (int)content->size()};
+}
+
binder::Status BinderIncrementalService::makeFile(
int32_t storageId, const std::string& path,
- const ::android::os::incremental::IncrementalNewFileParams& params, int32_t* _aidl_return) {
+ const ::android::os::incremental::IncrementalNewFileParams& params,
+ const ::std::optional<::std::vector<uint8_t>>& content, int32_t* _aidl_return) {
auto [err, fileId, nfp] = toMakeFileParams(params);
if (err) {
*_aidl_return = err;
return ok();
}
- *_aidl_return = mImpl.makeFile(storageId, path, 0777, fileId, nfp);
+ *_aidl_return = mImpl.makeFile(storageId, path, 0777, fileId, nfp, toSpan(content));
return ok();
}
binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 123849876095..0a89166f4868 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -58,7 +58,9 @@ public:
binder::Status makeDirectories(int32_t storageId, const std::string& path,
int32_t* _aidl_return) final;
binder::Status makeFile(int32_t storageId, const std::string& path,
- const IncrementalNewFileParams& params, int32_t* _aidl_return) final;
+ const IncrementalNewFileParams& params,
+ const ::std::optional<::std::vector<uint8_t>>& content,
+ int32_t* _aidl_return) final;
binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
const std::string& sourcePath, int64_t start, int64_t end,
int32_t* _aidl_return) final;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 10a508b06086..44a07a17824f 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -859,7 +859,7 @@ std::string IncrementalService::normalizePathToStorage(const IncFsMount& ifs, St
}
int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
- incfs::NewFileParams params) {
+ incfs::NewFileParams params, std::span<const uint8_t> data) {
if (auto ifs = getIfs(storage)) {
std::string normPath = normalizePathToStorage(*ifs, storage, path);
if (normPath.empty()) {
@@ -867,11 +867,15 @@ int IncrementalService::makeFile(StorageId storage, std::string_view path, int m
<< " failed to normalize: " << path;
return -EINVAL;
}
- auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params);
- if (err) {
+ if (auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params); err) {
LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile: " << err;
return err;
}
+ if (!data.empty()) {
+ if (auto err = setFileContent(ifs, id, path, data); err) {
+ return err;
+ }
+ }
return 0;
}
return -EINVAL;
@@ -1584,67 +1588,38 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
void IncrementalService::extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile,
ZipEntry& entry, const incfs::FileId& libFileId,
- std::string_view targetLibPath,
+ std::string_view debugLibPath,
Clock::time_point scheduledTs) {
if (!ifs) {
- LOG(INFO) << "Skipping zip file " << targetLibPath << " extraction for an expired mount";
+ LOG(INFO) << "Skipping zip file " << debugLibPath << " extraction for an expired mount";
return;
}
- auto libName = path::basename(targetLibPath);
auto startedTs = Clock::now();
// Write extracted data to new file
// NOTE: don't zero-initialize memory, it may take a while for nothing
auto libData = std::unique_ptr<uint8_t[]>(new uint8_t[entry.uncompressed_length]);
if (ExtractToMemory(zipFile, &entry, libData.get(), entry.uncompressed_length)) {
- LOG(ERROR) << "Failed to extract native lib zip entry: " << libName;
+ LOG(ERROR) << "Failed to extract native lib zip entry: " << path::basename(debugLibPath);
return;
}
auto extractFileTs = Clock::now();
- const auto writeFd = mIncFs->openForSpecialOps(ifs->control, libFileId);
- if (!writeFd.ok()) {
- LOG(ERROR) << "Failed to open write fd for: " << targetLibPath
- << " errno: " << writeFd.get();
- return;
- }
-
- auto openFileTs = Clock::now();
- const int numBlocks =
- (entry.uncompressed_length + constants().blockSize - 1) / constants().blockSize;
- std::vector<IncFsDataBlock> instructions(numBlocks);
- auto remainingData = std::span(libData.get(), entry.uncompressed_length);
- for (int i = 0; i < numBlocks; i++) {
- const auto blockSize = std::min<long>(constants().blockSize, remainingData.size());
- instructions[i] = IncFsDataBlock{
- .fileFd = writeFd.get(),
- .pageIndex = static_cast<IncFsBlockIndex>(i),
- .compression = INCFS_COMPRESSION_KIND_NONE,
- .kind = INCFS_BLOCK_KIND_DATA,
- .dataSize = static_cast<uint32_t>(blockSize),
- .data = reinterpret_cast<const char*>(remainingData.data()),
- };
- remainingData = remainingData.subspan(blockSize);
- }
- auto prepareInstsTs = Clock::now();
-
- size_t res = mIncFs->writeBlocks(instructions);
- if (res != instructions.size()) {
- LOG(ERROR) << "Failed to write data into: " << targetLibPath;
+ if (setFileContent(ifs, libFileId, debugLibPath,
+ std::span(libData.get(), entry.uncompressed_length))) {
return;
}
if (perfLoggingEnabled()) {
auto endFileTs = Clock::now();
- LOG(INFO) << "incfs: Extracted " << libName << "(" << entry.compressed_length << " -> "
- << entry.uncompressed_length << " bytes): " << elapsedMcs(startedTs, endFileTs)
+ LOG(INFO) << "incfs: Extracted " << path::basename(debugLibPath) << "("
+ << entry.compressed_length << " -> " << entry.uncompressed_length
+ << " bytes): " << elapsedMcs(startedTs, endFileTs)
<< "mcs, scheduling delay: " << elapsedMcs(scheduledTs, startedTs)
<< " extract: " << elapsedMcs(startedTs, extractFileTs)
- << " open: " << elapsedMcs(extractFileTs, openFileTs)
- << " prepare: " << elapsedMcs(openFileTs, prepareInstsTs)
- << " write: " << elapsedMcs(prepareInstsTs, endFileTs);
+ << " open/prepare/write: " << elapsedMcs(extractFileTs, endFileTs);
}
}
@@ -1677,6 +1652,55 @@ bool IncrementalService::waitForNativeBinariesExtraction(StorageId storage) {
return mRunning;
}
+int IncrementalService::setFileContent(const IfsMountPtr& ifs, const incfs::FileId& fileId,
+ std::string_view debugFilePath,
+ std::span<const uint8_t> data) const {
+ auto startTs = Clock::now();
+
+ const auto writeFd = mIncFs->openForSpecialOps(ifs->control, fileId);
+ if (!writeFd.ok()) {
+ LOG(ERROR) << "Failed to open write fd for: " << debugFilePath
+ << " errno: " << writeFd.get();
+ return writeFd.get();
+ }
+
+ const auto dataLength = data.size();
+
+ auto openFileTs = Clock::now();
+ const int numBlocks = (data.size() + constants().blockSize - 1) / constants().blockSize;
+ std::vector<IncFsDataBlock> instructions(numBlocks);
+ for (int i = 0; i < numBlocks; i++) {
+ const auto blockSize = std::min<long>(constants().blockSize, data.size());
+ instructions[i] = IncFsDataBlock{
+ .fileFd = writeFd.get(),
+ .pageIndex = static_cast<IncFsBlockIndex>(i),
+ .compression = INCFS_COMPRESSION_KIND_NONE,
+ .kind = INCFS_BLOCK_KIND_DATA,
+ .dataSize = static_cast<uint32_t>(blockSize),
+ .data = reinterpret_cast<const char*>(data.data()),
+ };
+ data = data.subspan(blockSize);
+ }
+ auto prepareInstsTs = Clock::now();
+
+ size_t res = mIncFs->writeBlocks(instructions);
+ if (res != instructions.size()) {
+ LOG(ERROR) << "Failed to write data into: " << debugFilePath;
+ return res;
+ }
+
+ if (perfLoggingEnabled()) {
+ auto endTs = Clock::now();
+ LOG(INFO) << "incfs: Set file content " << debugFilePath << "(" << dataLength
+ << " bytes): " << elapsedMcs(startTs, endTs)
+ << "mcs, open: " << elapsedMcs(startTs, openFileTs)
+ << " prepare: " << elapsedMcs(openFileTs, prepareInstsTs)
+ << " write: " << elapsedMcs(prepareInstsTs, endTs);
+ }
+
+ return 0;
+}
+
int IncrementalService::isFileFullyLoaded(StorageId storage, const std::string& path) const {
std::unique_lock l(mLock);
const auto ifs = getIfsLocked(storage);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index a49e0f36c9bc..d820417e73ed 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -127,7 +127,7 @@ public:
int setStorageParams(StorageId storage, bool enableReadLogs);
int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
- incfs::NewFileParams params);
+ incfs::NewFileParams params, std::span<const uint8_t> data);
int makeDir(StorageId storage, std::string_view path, int mode = 0755);
int makeDirs(StorageId storage, std::string_view path, int mode = 0755);
@@ -349,13 +349,16 @@ private:
int isFileFullyLoadedFromPath(const IncFsMount& ifs, std::string_view filePath) const;
float getLoadingProgressFromPath(const IncFsMount& ifs, std::string_view path) const;
+ int setFileContent(const IfsMountPtr& ifs, const incfs::FileId& fileId,
+ std::string_view debugFilePath, std::span<const uint8_t> data) const;
+
void registerAppOpsCallback(const std::string& packageName);
bool unregisterAppOpsCallback(const std::string& packageName);
void onAppOpChanged(const std::string& packageName);
void runJobProcessing();
void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry,
- const incfs::FileId& libFileId, std::string_view targetLibPath,
+ const incfs::FileId& libFileId, std::string_view debugLibPath,
Clock::time_point scheduledTs);
void runCmdLooper();
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 120182f09e8c..d61783ef59d2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -25,6 +25,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
@@ -54,6 +55,7 @@ import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
@@ -67,7 +69,6 @@ import android.app.IAlarmCompleteListener;
import android.app.IAlarmListener;
import android.app.PendingIntent;
import android.app.usage.UsageStatsManagerInternal;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
@@ -79,6 +80,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
@@ -100,11 +102,15 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.concurrent.Executor;
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -120,8 +126,6 @@ public class AlarmManagerServiceTest {
private AppStandbyInternal.AppIdleStateChangeListener mAppStandbyListener;
private AlarmManagerService.ChargingReceiver mChargingReceiver;
@Mock
- private ContentResolver mMockResolver;
- @Mock
private Context mMockContext;
@Mock
private IActivityManager mIActivityManager;
@@ -137,6 +141,9 @@ public class AlarmManagerServiceTest {
private AlarmManagerService.ClockReceiver mClockReceiver;
@Mock
private PowerManager.WakeLock mWakeLock;
+ @Mock
+ DeviceConfig.Properties mDeviceConfigProperties;
+ HashSet<String> mDeviceConfigKeys = new HashSet<>();
private MockitoSession mMockingSession;
private Injector mInjector;
@@ -253,6 +260,14 @@ public class AlarmManagerServiceTest {
PowerManager.WakeLock getAlarmWakeLock() {
return mWakeLock;
}
+
+ @Override
+ void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) {
+ // Do nothing.
+ // The tests become flaky with an error message of
+ // "IllegalStateException: Querying activity state off main thread is not allowed."
+ // when AlarmManager calls DeviceConfig.addOnPropertiesChangedListener().
+ }
}
@Before
@@ -260,6 +275,7 @@ public class AlarmManagerServiceTest {
mMockingSession = mockitoSession()
.initMocks(this)
.spyStatic(ActivityManager.class)
+ .spyStatic(DeviceConfig.class)
.mockStatic(LocalServices.class)
.spyStatic(Looper.class)
.mockStatic(Settings.Global.class)
@@ -283,9 +299,24 @@ public class AlarmManagerServiceTest {
eq(TEST_CALLING_USER), anyLong())).thenReturn(STANDBY_BUCKET_ACTIVE);
doReturn(Looper.getMainLooper()).when(Looper::myLooper);
- when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
- doReturn("min_futurity=0,min_interval=0").when(() ->
- Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
+ doReturn(mDeviceConfigKeys).when(mDeviceConfigProperties).getKeyset();
+ when(mDeviceConfigProperties.getLong(anyString(), anyLong()))
+ .thenAnswer((Answer<Long>) invocationOnMock -> {
+ Object[] args = invocationOnMock.getArguments();
+ return (Long) args[1];
+ });
+ when(mDeviceConfigProperties.getInt(anyString(), anyInt()))
+ .thenAnswer((Answer<Integer>) invocationOnMock -> {
+ Object[] args = invocationOnMock.getArguments();
+ return (Integer) args[1];
+ });
+ doAnswer((Answer<Void>) invocationOnMock -> null)
+ .when(() -> DeviceConfig.addOnPropertiesChangedListener(
+ anyString(), any(Executor.class),
+ any(DeviceConfig.OnPropertiesChangedListener.class)));
+ doReturn(mDeviceConfigProperties).when(
+ () -> DeviceConfig.getProperties(
+ eq(DeviceConfig.NAMESPACE_ALARM_MANAGER), ArgumentMatchers.<String>any()));
mInjector = new Injector(mMockContext);
mService = new AlarmManagerService(mMockContext, mInjector);
@@ -302,8 +333,6 @@ public class AlarmManagerServiceTest {
// Other boot phases don't matter
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
- assertEquals(0, mService.mConstants.MIN_FUTURITY);
- assertEquals(0, mService.mConstants.MIN_INTERVAL);
mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW;
ArgumentCaptor<AppStandbyInternal.AppIdleStateChangeListener> captor =
ArgumentCaptor.forClass(AppStandbyInternal.AppIdleStateChangeListener.class);
@@ -354,22 +383,27 @@ public class AlarmManagerServiceTest {
return mockPi;
}
+ private void setDeviceConfigLong(String key, long val) {
+ mDeviceConfigKeys.add(key);
+ doReturn(val).when(mDeviceConfigProperties).getLong(eq(key), anyLong());
+ mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
+ }
+
/**
* Lowers quotas to make testing feasible. Careful while calling as this will replace any
* existing settings for the calling test.
*/
private void setTestableQuotas() {
- final StringBuilder constantsBuilder = new StringBuilder();
- constantsBuilder.append(KEY_MIN_FUTURITY);
- constantsBuilder.append("=0,");
- // Capping active and working quotas to make testing feasible.
- constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
- constantsBuilder.append("=8,");
- constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]);
- constantsBuilder.append("=5,");
- doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver,
- Settings.Global.ALARM_MANAGER_CONSTANTS));
- mService.mConstants.onChange(false, null);
+ setDeviceConfigLong(KEY_MIN_FUTURITY, 0);
+ setDeviceConfigLong(KEY_MIN_INTERVAL, 0);
+ mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
+ mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]);
+ doReturn(8).when(mDeviceConfigProperties)
+ .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]), anyInt());
+ doReturn(5).when(mDeviceConfigProperties)
+ .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]), anyInt());
+
+ mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
}
@Test
@@ -427,25 +461,13 @@ public class AlarmManagerServiceTest {
@Test
public void testUpdateConstants() {
- final StringBuilder constantsBuilder = new StringBuilder();
- constantsBuilder.append(KEY_MIN_FUTURITY);
- constantsBuilder.append("=5,");
- constantsBuilder.append(KEY_MIN_INTERVAL);
- constantsBuilder.append("=10,");
- constantsBuilder.append(KEY_MAX_INTERVAL);
- constantsBuilder.append("=15,");
- constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_SHORT_TIME);
- constantsBuilder.append("=20,");
- constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_LONG_TIME);
- constantsBuilder.append("=25,");
- constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
- constantsBuilder.append("=30,");
- constantsBuilder.append(KEY_LISTENER_TIMEOUT);
- constantsBuilder.append("=35,");
-
- doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver,
- Settings.Global.ALARM_MANAGER_CONSTANTS));
- mService.mConstants.onChange(false, null);
+ setDeviceConfigLong(KEY_MIN_FUTURITY, 5);
+ setDeviceConfigLong(KEY_MIN_INTERVAL, 10);
+ setDeviceConfigLong(KEY_MAX_INTERVAL, 15);
+ setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 20);
+ setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, 25);
+ setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 30);
+ setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 35);
assertEquals(5, mService.mConstants.MIN_FUTURITY);
assertEquals(10, mService.mConstants.MIN_INTERVAL);
assertEquals(15, mService.mConstants.MAX_INTERVAL);
@@ -457,9 +479,7 @@ public class AlarmManagerServiceTest {
@Test
public void testMinFuturity() {
- doReturn("min_futurity=10").when(() ->
- Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
- mService.mConstants.onChange(false, null);
+ setDeviceConfigLong(KEY_MIN_FUTURITY, 10L);
assertEquals(10, mService.mConstants.MIN_FUTURITY);
final long triggerTime = mNowElapsedTest + 1;
final long expectedTriggerTime = mNowElapsedTest + mService.mConstants.MIN_FUTURITY;
@@ -469,9 +489,7 @@ public class AlarmManagerServiceTest {
@Test
public void testMinFuturityCoreUid() {
- doReturn("min_futurity=10").when(() ->
- Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
- mService.mConstants.onChange(false, null);
+ setDeviceConfigLong(KEY_MIN_FUTURITY, 10L);
assertEquals(10, mService.mConstants.MIN_FUTURITY);
final long triggerTime = mNowElapsedTest + 1;
doReturn(true).when(() -> UserHandle.isCore(TEST_CALLING_UID));
@@ -769,7 +787,7 @@ public class AlarmManagerServiceTest {
}
@Test
- public void testAlarmRestrictedInBatterSaver() throws Exception {
+ public void testAlarmRestrictedInBatterySaver() throws Exception {
final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor =
ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class);
verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 43a396d8e5d7..b8dbd6267bc5 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -302,4 +302,42 @@ public class DisplayModeDirectorTest {
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
}
+
+ @Test
+ public void testVotingWithAlwaysRespectAppRequest() {
+ final int displayId = 0;
+ DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(displayId, votes);
+ votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE, Vote.forRefreshRates(60, 90));
+ votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+
+
+ director.injectVotesByDisplay(votesByDisplay);
+ Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse();
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60);
+
+ director.setShouldAlwaysRespectAppRequestedMode(true);
+ Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue();
+ desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+
+ director.setShouldAlwaysRespectAppRequestedMode(false);
+ Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse();
+
+ desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
index 870a27417cd2..63ad53bcab4a 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
@@ -110,7 +110,7 @@ public class ActiveSourceActionTest {
mHdmiControlService.setIoLooper(looper);
mNativeWrapper = new FakeNativeWrapper();
HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
- this.mHdmiControlService, mNativeWrapper);
+ this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(hdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
index c0d5f7b5aa9e..08f558e6d99c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
@@ -120,8 +120,8 @@ public class ArcInitiationActionFromAvrTest {
Looper looper = mTestLooper.getLooper();
mHdmiControlService.setIoLooper(looper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(this.mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
index f986a70804f6..4afbbf741102 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -114,8 +114,8 @@ public class ArcTerminationActionFromAvrTest {
Looper looper = mTestLooper.getLooper();
mHdmiControlService.setIoLooper(looper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(this.mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 55c925f7f7aa..dd4c0814a441 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -89,8 +89,8 @@ public class HdmiCecControllerTest {
mMyLooper = mTestLooper.getLooper();
mHdmiControlService = new MyHdmiControlService(InstrumentationRegistry.getTargetContext());
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
}
/** Tests for {@link HdmiCecController#allocateLogicalAddress} */
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 953a03c2d9e3..415ae0731edb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -188,8 +188,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
mHdmiControlService.setIoLooper(mMyLooper);
mNativeWrapper = new FakeNativeWrapper();
mNativeWrapper.setPhysicalAddress(SELF_PHYSICAL_ADDRESS);
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 0c35797b38ea..d160a3fab186 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -119,8 +119,8 @@ public class HdmiCecLocalDevicePlaybackTest {
mHdmiCecLocalDevicePlayback.init();
mHdmiControlService.setIoLooper(mMyLooper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index 526c1d07296f..e54f2c9e6b2e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -117,9 +117,8 @@ public class HdmiCecLocalDeviceTest {
}
};
mHdmiControlService.setIoLooper(mTestLooper.getLooper());
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(
- mHdmiControlService, new FakeNativeWrapper());
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, new FakeNativeWrapper(), mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiLocalDevice = new MyHdmiCecLocalDevice(mHdmiControlService, DEVICE_TV);
mMessageValidator =
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index b88573ae168a..ce1cdf369076 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -97,8 +97,8 @@ public class HdmiCecLocalDeviceTvTest {
mHdmiCecLocalDeviceTv.init();
mHdmiControlService.setIoLooper(mMyLooper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
index c6cf9b116a1d..7560a34e63cc 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
@@ -15,28 +15,28 @@
*/
package com.android.server.hdmi;
-import static android.os.SystemClock.sleep;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.os.Looper;
-import android.os.SystemProperties;
import android.os.test.TestLooper;
-import android.util.Slog;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
-import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.ArrayList;
+
/**
* Tests for {@link HdmiControlServiceBinderAPITest} class.
*/
@@ -158,8 +158,8 @@ public class HdmiControlServiceBinderAPITest {
mHdmiControlService.setIoLooper(mMyLooper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 31cf59ee7bde..4849dd417041 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -158,8 +158,8 @@ public class HdmiControlServiceTest {
mHdmiControlService.setIoLooper(mMyLooper);
mNativeWrapper = new FakeNativeWrapper();
- mHdmiCecController =
- HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 2bd0e55f7d21..2d6605ae222f 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -511,10 +511,24 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential password = newPassword("password");
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID));
+ assertNoOrphanedFilesLeft(PRIMARY_USER_ID);
+ }
+
+ @Test
+ public void testAddingEscrowToken_NoOrphanedFilesLeft() throws Exception {
+ final byte[] token = "some-high-entropy-secure-token".getBytes();
+ for (int i = 0; i < 16; i++) {
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+ mLocalService.removeEscrowToken(handle, PRIMARY_USER_ID);
+ }
+ assertNoOrphanedFilesLeft(PRIMARY_USER_ID);
+ }
+ private void assertNoOrphanedFilesLeft(int userId) {
String handleString = String.format("%016x",
- mService.getSyntheticPasswordHandleLocked(PRIMARY_USER_ID));
- File directory = mStorage.getSyntheticPasswordDirectoryForUser(PRIMARY_USER_ID);
+ mService.getSyntheticPasswordHandleLocked(userId));
+ File directory = mStorage.getSyntheticPasswordDirectoryForUser(userId);
for (File file : directory.listFiles()) {
String[] parts = file.getName().split("\\.");
if (!parts[0].equals(handleString) && !parts[0].equals("0000000000000000")) {
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 a60f93a3b14a..caf8a720e26c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1142,7 +1142,8 @@ public class ActivityStackTests extends WindowTestsBase {
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(mTask).build();
topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING;
- mStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, topActivity);
+ mStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, topActivity,
+ "test");
verify(mStack).completePauseLocked(anyBoolean(), eq(topActivity));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 608305c33168..8c02faf7ac09 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -22,7 +22,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
@@ -38,20 +37,22 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import android.app.StatusBarManager;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
-import android.view.test.InsetsModeSession;
import androidx.test.filters.SmallTest;
-import org.junit.AfterClass;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,19 +60,6 @@ import org.junit.runner.RunWith;
@Presubmit
@RunWith(WindowTestRunner.class)
public class InsetsPolicyTest extends WindowTestsBase {
- private static InsetsModeSession sInsetsModeSession;
-
- @BeforeClass
- public static void setUpOnce() {
- // To let the insets provider control the insets visibility, the insets mode has to be
- // NEW_INSETS_MODE_FULL.
- sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
- }
-
- @AfterClass
- public static void tearDownOnce() {
- sInsetsModeSession.close();
- }
@Before
public void setup() {
@@ -222,6 +210,23 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertNotNull(fullscreenAppControls);
assertEquals(1, fullscreenAppControls.length);
assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType());
+
+ // Assume mFocusedWindow is updated but mTopFullscreenOpaqueWindowState hasn't.
+ final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp");
+ final InsetsState newRequestedState = new InsetsState();
+ newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState);
+ // Make sure status bar is hidden by previous insets state.
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp);
+
+ final StatusBarManagerInternal sbmi =
+ mDisplayContent.getDisplayPolicy().getStatusBarManagerInternal();
+ clearInvocations(sbmi);
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(newFocusedFullscreenApp);
+ // The status bar should be shown by newFocusedFullscreenApp even
+ // mTopFullscreenOpaqueWindowState is still fullscreenApp.
+ verify(sbmi).setWindowState(mDisplayContent.mDisplayId, StatusBarManager.WINDOW_STATUS_BAR,
+ StatusBarManager.WINDOW_STATE_SHOWING);
}
@UseTestDisplay(addWindows = W_ACTIVITY)
@@ -312,6 +317,15 @@ public class InsetsPolicyTest extends WindowTestsBase {
final InsetsState state = policy.getInsetsForDispatch(mAppWindow);
state.setSourceVisible(ITYPE_STATUS_BAR, true);
state.setSourceVisible(ITYPE_NAVIGATION_BAR, true);
+
+ final InsetsState clientState = mAppWindow.getInsetsState();
+ // The transient bar states for client should be invisible.
+ assertFalse(clientState.getSource(ITYPE_STATUS_BAR).isVisible());
+ assertFalse(clientState.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+ // The original state shouldn't be modified.
+ assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible());
+ assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+
policy.onInsetsModified(mAppWindow, state);
waitUntilWindowAnimatorIdle();
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 59f8cc8c3412..4a4974355ea2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -23,7 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -43,15 +42,11 @@ import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
-import android.util.IntArray;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
-import android.view.test.InsetsModeSession;
import androidx.test.filters.SmallTest;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,19 +54,6 @@ import org.junit.runner.RunWith;
@Presubmit
@RunWith(WindowTestRunner.class)
public class InsetsStateControllerTest extends WindowTestsBase {
- private static InsetsModeSession sInsetsModeSession;
-
- @BeforeClass
- public static void setUpOnce() {
- // To let the insets provider control the insets visibility, the insets mode has to be
- // NEW_INSETS_MODE_FULL.
- sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
- }
-
- @AfterClass
- public static void tearDownOnce() {
- sInsetsModeSession.close();
- }
@Test
public void testStripForDispatch_notOwn() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 6a29c5b5424a..da3319acca24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -318,6 +318,9 @@ public class SystemServicesTestRule implements TestRule {
display.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(display);
final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
+
+ // Set the default focused TDA.
+ display.setLastFocusedTaskDisplayArea(taskDisplayArea);
spyOn(taskDisplayArea);
final Task homeStack = taskDisplayArea.getStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index bc3b3a4d7ad1..e71f7ec54b0e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -242,6 +243,40 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
assertEquals(rootWindowContainer.getOrientation(), rootHomeTask.getOrientation());
}
+ @Test
+ public void testIsLastFocused() {
+ final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
+ final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
+ mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
+ FEATURE_VENDOR_FIRST);
+ final Task firstStack = firstTaskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final Task secondStack = secondTaskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setStack(firstStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setStack(secondStack).build();
+
+ // Activity on TDA1 is focused
+ mDisplayContent.setFocusedApp(firstActivity);
+
+ assertThat(firstTaskDisplayArea.isLastFocused()).isTrue();
+ assertThat(secondTaskDisplayArea.isLastFocused()).isFalse();
+
+ // No focused app, TDA1 is still recorded as last focused.
+ mDisplayContent.setFocusedApp(null);
+
+ assertThat(firstTaskDisplayArea.isLastFocused()).isTrue();
+ assertThat(secondTaskDisplayArea.isLastFocused()).isFalse();
+
+ // Activity on TDA2 is focused
+ mDisplayContent.setFocusedApp(secondActivity);
+
+ assertThat(firstTaskDisplayArea.isLastFocused()).isFalse();
+ assertThat(secondTaskDisplayArea.isLastFocused()).isTrue();
+ }
+
private void assertGetOrCreateStack(int windowingMode, int activityType, Task candidateTask,
boolean reuseCandidate) {
final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a908bfef98de..d2b7ac4c3b24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -33,6 +33,7 @@ import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -1001,7 +1002,7 @@ public class TaskRecordTests extends WindowTestsBase {
public void testNotSpecifyOrientationByFloatingTask() {
final Task task = getTestTask();
final ActivityRecord activity = task.getTopMostActivity();
- final WindowContainer<?> taskDisplayArea = task.getParent();
+ final TaskDisplayArea taskDisplayArea = task.getDisplayArea();
activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, taskDisplayArea.getOrientation());
@@ -1012,6 +1013,42 @@ public class TaskRecordTests extends WindowTestsBase {
}
@Test
+ public void testNotSpecifyOrientation_taskDisplayAreaNotFocused() {
+ final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
+ final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
+ mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
+ FEATURE_VENDOR_FIRST);
+ final Task firstStack = firstTaskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final Task secondStack = secondTaskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setStack(firstStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setStack(secondStack).build();
+ firstActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ secondActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+
+ // Activity on TDA1 is focused
+ mDisplayContent.setFocusedApp(firstActivity);
+
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, firstTaskDisplayArea.getOrientation());
+ assertEquals(SCREEN_ORIENTATION_UNSET, secondTaskDisplayArea.getOrientation());
+
+ // No focused app, TDA1 is still recorded as last focused.
+ mDisplayContent.setFocusedApp(null);
+
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, firstTaskDisplayArea.getOrientation());
+ assertEquals(SCREEN_ORIENTATION_UNSET, secondTaskDisplayArea.getOrientation());
+
+ // Activity on TDA2 is focused
+ mDisplayContent.setFocusedApp(secondActivity);
+
+ assertEquals(SCREEN_ORIENTATION_UNSET, firstTaskDisplayArea.getOrientation());
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, secondTaskDisplayArea.getOrientation());
+ }
+
+ @Test
public void testNotifyOrientationChangeCausedByConfigurationChange() {
final Task task = getTestTask();
final ActivityRecord activity = task.getTopMostActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 213c1f52aa37..ee16a76bcff8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -156,6 +156,10 @@ class TestDisplayContent extends DisplayContent {
// threads immediately after adding it to hierarchy. Calling doAnswer() type of stubbing
// reduces chance of races, but still doesn't eliminate race conditions.
mService.mRootWindowContainer.addChild(newDisplay, mPosition);
+
+ // Set the default focused TDA.
+ newDisplay.setLastFocusedTaskDisplayArea(newDisplay.getDefaultTaskDisplayArea());
+
return newDisplay;
}
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index edbdd4e94ac8..b6506b408714 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -58,7 +58,9 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
+import java.util.function.BiFunction;
/**
* Helper for {@link SoundTrigger} APIs. Supports two types of models:
@@ -116,6 +118,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private PowerSaveModeListener mPowerSaveModeListener;
+ private final BiFunction<Integer, SoundTrigger.StatusListener, SoundTriggerModule>
+ mModuleProvider;
+
// Handler to process call state changes will delay to allow time for the audio
// and sound trigger HALs to process the end of call notifications
// before we re enable pending recognition requests.
@@ -123,15 +128,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private static final int MSG_CALL_STATE_CHANGED = 0;
private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000;
- SoundTriggerHelper(Context context) {
+ SoundTriggerHelper(Context context,
+ @NonNull BiFunction<Integer, SoundTrigger.StatusListener,
+ SoundTriggerModule> moduleProvider) {
ArrayList <ModuleProperties> modules = new ArrayList<>();
+ mModuleProvider = moduleProvider;
int status = SoundTrigger.listModules(modules);
mContext = context;
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mModelDataMap = new HashMap<UUID, ModelData>();
mKeyphraseUuidMap = new HashMap<Integer, UUID>();
- mPhoneStateListener = new MyCallStateListener();
if (status != SoundTrigger.STATUS_OK || modules.size() == 0) {
Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size());
mModuleProperties = null;
@@ -145,6 +152,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
if (looper == null) {
looper = Looper.getMainLooper();
}
+ mPhoneStateListener = new MyCallStateListener(looper);
if (looper != null) {
mHandler = new Handler(looper) {
@Override
@@ -264,7 +272,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private int prepareForRecognition(ModelData modelData) {
if (mModule == null) {
- mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null);
+ mModule = mModuleProvider.apply(mModuleProperties.getId(), this);
if (mModule == null) {
Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module");
return STATUS_ERROR;
@@ -1042,6 +1050,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
class MyCallStateListener extends PhoneStateListener {
+ MyCallStateListener(@NonNull Looper looper) {
+ super(Objects.requireNonNull(looper));
+ }
+
@Override
public void onCallStateChanged(int state, String arg1) {
if (DBG) Slog.d(TAG, "onCallStateChanged: " + state);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
index 54dffdc4c13a..f77d4907cf03 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -16,6 +16,7 @@
package com.android.server.soundtrigger;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.ModelParams;
@@ -25,6 +26,7 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.media.permission.Identity;
import com.android.server.voiceinteraction.VoiceInteractionManagerService;
@@ -35,97 +37,114 @@ import java.io.PrintWriter;
* Provides a local service for managing voice-related recoginition models. This is primarily used
* by the {@link VoiceInteractionManagerService}.
*/
-public abstract class SoundTriggerInternal {
+public interface SoundTriggerInternal {
/**
- * Return codes for {@link #startRecognition(int, KeyphraseSoundModel,
+ * Return codes for {@link Session#startRecognition(int, KeyphraseSoundModel,
* IRecognitionStatusCallback, RecognitionConfig)},
- * {@link #stopRecognition(int, IRecognitionStatusCallback)}
+ * {@link Session#stopRecognition(int, IRecognitionStatusCallback)}
*/
- public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
- public static final int STATUS_OK = SoundTrigger.STATUS_OK;
+ int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
+ int STATUS_OK = SoundTrigger.STATUS_OK;
- /**
- * Starts recognition for the given keyphraseId.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * the recognition is to be started.
- * @param soundModel The sound model to use for recognition.
- * @param listener The listener for the recognition events related to the given keyphrase.
- * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
- */
- public abstract int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
- IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig);
+ Session attachAsOriginator(@NonNull Identity originatorIdentity);
+
+ Session attachAsMiddleman(@NonNull Identity middlemanIdentity,
+ @NonNull Identity originatorIdentity);
/**
- * Stops recognition for the given {@link Keyphrase} if a recognition is
- * currently active.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * the recognition is to be stopped.
- * @param listener The listener for the recognition events related to the given keyphrase.
- *
- * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ * Dumps service-wide information.
*/
- public abstract int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener);
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args);
- public abstract ModuleProperties getModuleProperties();
+ interface Session {
+ /**
+ * Starts recognition for the given keyphraseId.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be started.
+ * @param soundModel The sound model to use for recognition.
+ * @param listener The listener for the recognition events related to the given
+ * keyphrase.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig);
- /**
- * Set a model specific {@link ModelParams} with the given value. This
- * parameter will keep its value for the duration the model is loaded regardless of starting and
- * stopping recognition. Once the model is unloaded, the value will be lost.
- * {@link SoundTriggerInternal#queryParameter} should be checked first before calling this
- * method.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * to modify model parameters
- * @param modelParam {@link ModelParams}
- * @param value Value to set
- * @return - {@link SoundTrigger#STATUS_OK} in case of success
- * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
- * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
- * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
- * if API is not supported by HAL
- */
- public abstract int setParameter(int keyphraseId, @ModelParams int modelParam, int value);
+ /**
+ * Stops recognition for the given {@link Keyphrase} if a recognition is
+ * currently active.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be stopped.
+ * @param listener The listener for the recognition events related to the given
+ * keyphrase.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener);
- /**
- * Get a model specific {@link ModelParams}. This parameter will keep its value
- * for the duration the model is loaded regardless of starting and stopping recognition.
- * Once the model is unloaded, the value will be lost. If the value is not set, a default
- * value is returned. See ModelParams for parameter default values.
- * {@link SoundTriggerInternal#queryParameter} should be checked first before calling this
- * method.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * to modify model parameters
- * @param modelParam {@link ModelParams}
- * @return value of parameter
- * @throws UnsupportedOperationException if hal or model do not support this API.
- * queryParameter should be checked first.
- * @throws IllegalArgumentException if invalid model handle or parameter is passed.
- * queryParameter should be checked first.
- */
- public abstract int getParameter(int keyphraseId, @ModelParams int modelParam);
+ ModuleProperties getModuleProperties();
- /**
- * Determine if parameter control is supported for the given model handle.
- * This method should be checked prior to calling {@link SoundTriggerInternal#setParameter}
- * or {@link SoundTriggerInternal#getParameter}.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * to modify model parameters
- * @param modelParam {@link ModelParams}
- * @return supported range of parameter, null if not supported
- */
- @Nullable
- public abstract ModelParamRange queryParameter(int keyphraseId,
- @ModelParams int modelParam);
+ /**
+ * Set a model specific {@link ModelParams} with the given value. This
+ * parameter will keep its value for the duration the model is loaded regardless of starting
+ * and
+ * stopping recognition. Once the model is unloaded, the value will be lost.
+ * {@link #queryParameter} should be checked first before calling this
+ * method.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * to modify model parameters
+ * @param modelParam {@link ModelParams}
+ * @param value Value to set
+ * @return - {@link SoundTrigger#STATUS_OK} in case of success
+ * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+ * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
+ * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
+ * if API is not supported by HAL
+ */
+ int setParameter(int keyphraseId, @ModelParams int modelParam, int value);
- /**
- * Unloads (and stops if running) the given keyphraseId
- */
- public abstract int unloadKeyphraseModel(int keyphaseId);
+ /**
+ * Get a model specific {@link ModelParams}. This parameter will keep its value
+ * for the duration the model is loaded regardless of starting and stopping recognition.
+ * Once the model is unloaded, the value will be lost. If the value is not set, a default
+ * value is returned. See ModelParams for parameter default values.
+ * {{@link #queryParameter}} should be checked first before calling this
+ * method.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * to modify model parameters
+ * @param modelParam {@link ModelParams}
+ * @return value of parameter
+ * @throws UnsupportedOperationException if hal or model do not support this API.
+ * queryParameter should be checked first.
+ * @throws IllegalArgumentException if invalid model handle or parameter is passed.
+ * queryParameter should be checked first.
+ */
+ int getParameter(int keyphraseId, @ModelParams int modelParam);
+
+ /**
+ * Determine if parameter control is supported for the given model handle.
+ * This method should be checked prior to calling {@link #setParameter}
+ * or {@link #getParameter}.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * to modify model parameters
+ * @param modelParam {@link ModelParams}
+ * @return supported range of parameter, null if not supported
+ */
+ @Nullable
+ ModelParamRange queryParameter(int keyphraseId,
+ @ModelParams int modelParam);
+
+ /**
+ * Unloads (and stops if running) the given keyphraseId
+ */
+ int unloadKeyphraseModel(int keyphaseId);
- public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+ /**
+ * Dumps session-wide information.
+ */
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+ }
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 26d46dbd2ab7..a73e73e37fff 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -17,6 +17,7 @@
package com.android.server.soundtrigger;
import static android.Manifest.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE;
+import static android.Manifest.permission.SOUNDTRIGGER_DELEGATE_IDENTITY;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
import static android.content.Context.BIND_INCLUDE_CAPABILITIES;
@@ -25,7 +26,6 @@ import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.hardware.soundtrigger.SoundTrigger.STATUS_BAD_VALUE;
import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
-import static android.hardware.soundtrigger.SoundTrigger.STATUS_NO_INIT;
import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
import static android.provider.Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY;
import static android.provider.Settings.Global.SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT;
@@ -35,6 +35,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -54,6 +55,10 @@ import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
+import android.media.permission.Identity;
+import android.media.permission.IdentityContext;
+import android.media.permission.PermissionUtil;
+import android.media.permission.SafeCloseable;
import android.media.soundtrigger.ISoundTriggerDetectionService;
import android.media.soundtrigger.ISoundTriggerDetectionServiceClient;
import android.media.soundtrigger.SoundTriggerDetectionService;
@@ -75,6 +80,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.ISoundTriggerService;
+import com.android.internal.app.ISoundTriggerSession;
import com.android.server.SystemService;
import java.io.FileDescriptor;
@@ -104,10 +110,6 @@ public class SoundTriggerService extends SystemService {
private final SoundTriggerServiceStub mServiceStub;
private final LocalSoundTriggerService mLocalSoundTriggerService;
private SoundTriggerDbHelper mDbHelper;
- private SoundTriggerHelper mSoundTriggerHelper;
- private final TreeMap<UUID, SoundModel> mLoadedModels;
- private Object mCallbacksLock;
- private final TreeMap<UUID, IRecognitionStatusCallback> mCallbacks;
class SoundModelStatTracker {
private class SoundModelStat {
@@ -192,9 +194,6 @@ public class SoundTriggerService extends SystemService {
mContext = context;
mServiceStub = new SoundTriggerServiceStub();
mLocalSoundTriggerService = new LocalSoundTriggerService(context);
- mLoadedModels = new TreeMap<UUID, SoundModel>();
- mCallbacksLock = new Object();
- mCallbacks = new TreeMap<>();
mLock = new Object();
mSoundModelStatTracker = new SoundModelStatTracker();
}
@@ -208,34 +207,54 @@ public class SoundTriggerService extends SystemService {
@Override
public void onBootPhase(int phase) {
Slog.d(TAG, "onBootPhase: " + phase + " : " + isSafeMode());
- if (PHASE_DEVICE_SPECIFIC_SERVICES_READY == phase) {
- if (isSafeMode()) {
- Slog.w(TAG, "not enabling SoundTriggerService in safe mode");
- return;
- }
-
- initSoundTriggerHelper();
- mLocalSoundTriggerService.setSoundTriggerHelper(mSoundTriggerHelper);
- } else if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
+ if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
mDbHelper = new SoundTriggerDbHelper(mContext);
}
}
- private synchronized void initSoundTriggerHelper() {
- if (mSoundTriggerHelper == null) {
- mSoundTriggerHelper = new SoundTriggerHelper(mContext);
- }
+ private SoundTriggerHelper newSoundTriggerHelper() {
+ Identity middlemanIdentity = new Identity();
+ middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
+
+ Identity originatorIdentity = IdentityContext.getNonNull();
+
+ return new SoundTriggerHelper(mContext,
+ (moduleId, listener) -> SoundTrigger.attachModuleAsMiddleman(moduleId, listener,
+ null,
+ middlemanIdentity, originatorIdentity));
}
- private synchronized boolean isInitialized() {
- if (mSoundTriggerHelper == null ) {
- Slog.e(TAG, "SoundTriggerHelper not initialized.");
- return false;
+ class SoundTriggerServiceStub extends ISoundTriggerService.Stub {
+ @Override
+ public ISoundTriggerSession attachAsOriginator(Identity originatorIdentity) {
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
+ originatorIdentity)) {
+ return new SoundTriggerSessionStub(newSoundTriggerHelper());
+ }
+ }
+
+ @Override
+ public ISoundTriggerSession attachAsMiddleman(Identity originatorIdentity,
+ Identity middlemanIdentity) {
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityIndirect(mContext,
+ SOUNDTRIGGER_DELEGATE_IDENTITY, middlemanIdentity,
+ originatorIdentity)) {
+ return new SoundTriggerSessionStub(newSoundTriggerHelper());
+ }
}
- return true;
}
- class SoundTriggerServiceStub extends ISoundTriggerService.Stub {
+ class SoundTriggerSessionStub extends ISoundTriggerSession.Stub {
+ private final SoundTriggerHelper mSoundTriggerHelper;
+ private final TreeMap<UUID, SoundModel> mLoadedModels = new TreeMap<>();
+ private final Object mCallbacksLock = new Object();
+ private final TreeMap<UUID, IRecognitionStatusCallback> mCallbacks = new TreeMap<>();
+
+ SoundTriggerSessionStub(
+ SoundTriggerHelper soundTriggerHelper) {
+ mSoundTriggerHelper = soundTriggerHelper;
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -255,7 +274,6 @@ public class SoundTriggerService extends SystemService {
public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback,
RecognitionConfig config) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
}
@@ -291,8 +309,6 @@ public class SoundTriggerService extends SystemService {
sEventLogger.log(new SoundTriggerLogger.StringEvent("stopRecognition(): Uuid : "
+ parcelUuid));
- if (!isInitialized()) return STATUS_ERROR;
-
int ret = mSoundTriggerHelper.stopGenericRecognition(parcelUuid.getUuid(), callback);
if (ret == STATUS_OK) {
mSoundModelStatTracker.onStop(parcelUuid.getUuid());
@@ -338,13 +354,11 @@ public class SoundTriggerService extends SystemService {
sEventLogger.log(new SoundTriggerLogger.StringEvent("deleteSoundModel(): id = "
+ soundModelId));
- if (isInitialized()) {
- // Unload the model if it is loaded.
- mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
+ // Unload the model if it is loaded.
+ mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
- // Stop tracking recognition if it is started.
- mSoundModelStatTracker.onStop(soundModelId.getUuid());
- }
+ // Stop tracking recognition if it is started.
+ mSoundModelStatTracker.onStop(soundModelId.getUuid());
mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
}
@@ -352,7 +366,6 @@ public class SoundTriggerService extends SystemService {
@Override
public int loadGenericSoundModel(GenericSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_ERROR;
if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
@@ -387,7 +400,6 @@ public class SoundTriggerService extends SystemService {
@Override
public int loadKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_ERROR;
if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
@@ -440,7 +452,6 @@ public class SoundTriggerService extends SystemService {
enforceDetectionPermissions(detectionService);
- if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "startRecognition(): id = " + soundModelId);
}
@@ -510,7 +521,6 @@ public class SoundTriggerService extends SystemService {
@Override
public int stopRecognitionForService(ParcelUuid soundModelId) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "stopRecognition(): id = " + soundModelId);
}
@@ -577,7 +587,6 @@ public class SoundTriggerService extends SystemService {
@Override
public int unloadSoundModel(ParcelUuid soundModelId) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "unloadSoundModel(): id = " + soundModelId);
}
@@ -628,7 +637,6 @@ public class SoundTriggerService extends SystemService {
@Override
public boolean isRecognitionActive(ParcelUuid parcelUuid) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return false;
synchronized (mCallbacksLock) {
IRecognitionStatusCallback callback = mCallbacks.get(parcelUuid.getUuid());
if (callback == null) {
@@ -642,7 +650,6 @@ public class SoundTriggerService extends SystemService {
public int getModelState(ParcelUuid soundModelId) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
int ret = STATUS_ERROR;
- if (!isInitialized()) return ret;
if (DEBUG) {
Slog.i(TAG, "getModelState(): id = " + soundModelId);
}
@@ -681,7 +688,6 @@ public class SoundTriggerService extends SystemService {
@Nullable
public ModuleProperties getModuleProperties() {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return null;
if (DEBUG) {
Slog.i(TAG, "getModuleProperties()");
}
@@ -698,7 +704,6 @@ public class SoundTriggerService extends SystemService {
public int setParameter(ParcelUuid soundModelId,
@ModelParams int modelParam, int value) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return STATUS_NO_INIT;
if (DEBUG) {
Slog.d(TAG, "setParameter(): id=" + soundModelId
+ ", param=" + modelParam
@@ -731,9 +736,6 @@ public class SoundTriggerService extends SystemService {
@ModelParams int modelParam)
throws UnsupportedOperationException, IllegalArgumentException {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) {
- throw new UnsupportedOperationException("SoundTriggerHelper not initialized");
- }
if (DEBUG) {
Slog.d(TAG, "getParameter(): id=" + soundModelId
+ ", param=" + modelParam);
@@ -763,7 +765,6 @@ public class SoundTriggerService extends SystemService {
public ModelParamRange queryParameter(@NonNull ParcelUuid soundModelId,
@ModelParams int modelParam) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
- if (!isInitialized()) return null;
if (DEBUG) {
Slog.d(TAG, "queryParameter(): id=" + soundModelId
+ ", param=" + modelParam);
@@ -788,712 +789,745 @@ public class SoundTriggerService extends SystemService {
return mSoundTriggerHelper.queryParameter(soundModel.getUuid(), modelParam);
}
}
- }
-
- /**
- * Counts the number of operations added in the last 24 hours.
- */
- private static class NumOps {
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private int[] mNumOps = new int[24];
- @GuardedBy("mLock")
- private long mLastOpsHourSinceBoot;
/**
- * Clear buckets of new hours that have elapsed since last operation.
+ * Local end for a {@link SoundTriggerDetectionService}. Operations are queued up and
+ * executed when the service connects.
*
- * <p>I.e. when the last operation was triggered at 1:40 and the current operation was
- * triggered at 4:03, the buckets "2, 3, and 4" are cleared.
+ * <p>If operations take too long they are forcefully aborted.
*
- * @param currentTime Current elapsed time since boot in ns
+ * <p>This also limits the amount of operations in 24 hours.
*/
- void clearOldOps(long currentTime) {
- synchronized (mLock) {
- long numHoursSinceBoot = TimeUnit.HOURS.convert(currentTime, TimeUnit.NANOSECONDS);
-
- // Clear buckets of new hours that have elapsed since last operation
- // I.e. when the last operation was triggered at 1:40 and the current
- // operation was triggered at 4:03, the bucket "2, 3, and 4" is cleared
- if (mLastOpsHourSinceBoot != 0) {
- for (long hour = mLastOpsHourSinceBoot + 1; hour <= numHoursSinceBoot; hour++) {
- mNumOps[(int) (hour % 24)] = 0;
+ private class RemoteSoundTriggerDetectionService
+ extends IRecognitionStatusCallback.Stub implements ServiceConnection {
+ private static final int MSG_STOP_ALL_PENDING_OPERATIONS = 1;
+
+ private final Object mRemoteServiceLock = new Object();
+
+ /** UUID of the model the service is started for */
+ private final @NonNull
+ ParcelUuid mPuuid;
+ /** Params passed into the start method for the service */
+ private final @Nullable
+ Bundle mParams;
+ /** Component name passed when starting the service */
+ private final @NonNull
+ ComponentName mServiceName;
+ /** User that started the service */
+ private final @NonNull
+ UserHandle mUser;
+ /** Configuration of the recognition the service is handling */
+ private final @NonNull
+ RecognitionConfig mRecognitionConfig;
+ /** Wake lock keeping the remote service alive */
+ private final @NonNull
+ PowerManager.WakeLock mRemoteServiceWakeLock;
+
+ private final @NonNull
+ Handler mHandler;
+
+ /** Callbacks that are called by the service */
+ private final @NonNull
+ ISoundTriggerDetectionServiceClient mClient;
+
+ /** Operations that are pending because the service is not yet connected */
+ @GuardedBy("mRemoteServiceLock")
+ private final ArrayList<Operation> mPendingOps = new ArrayList<>();
+ /** Operations that have been send to the service but have no yet finished */
+ @GuardedBy("mRemoteServiceLock")
+ private final ArraySet<Integer> mRunningOpIds = new ArraySet<>();
+ /** The number of operations executed in each of the last 24 hours */
+ private final NumOps mNumOps;
+
+ /** The service binder if connected */
+ @GuardedBy("mRemoteServiceLock")
+ private @Nullable
+ ISoundTriggerDetectionService mService;
+ /** Whether the service has been bound */
+ @GuardedBy("mRemoteServiceLock")
+ private boolean mIsBound;
+ /** Whether the service has been destroyed */
+ @GuardedBy("mRemoteServiceLock")
+ private boolean mIsDestroyed;
+ /**
+ * Set once a final op is scheduled. No further ops can be added and the service is
+ * destroyed once the op finishes.
+ */
+ @GuardedBy("mRemoteServiceLock")
+ private boolean mDestroyOnceRunningOpsDone;
+
+ /** Total number of operations performed by this service */
+ @GuardedBy("mRemoteServiceLock")
+ private int mNumTotalOpsPerformed;
+
+ /**
+ * Create a new remote sound trigger detection service. This only binds to the service
+ * when operations are in flight. Each operation has a certain time it can run. Once no
+ * operations are allowed to run anymore, {@link #stopAllPendingOperations() all
+ * operations are aborted and stopped} and the service is disconnected.
+ *
+ * @param modelUuid The UUID of the model the recognition is for
+ * @param params The params passed to each method of the service
+ * @param serviceName The component name of the service
+ * @param user The user of the service
+ * @param config The configuration of the recognition
+ */
+ public RemoteSoundTriggerDetectionService(@NonNull UUID modelUuid,
+ @Nullable Bundle params, @NonNull ComponentName serviceName,
+ @NonNull UserHandle user, @NonNull RecognitionConfig config) {
+ mPuuid = new ParcelUuid(modelUuid);
+ mParams = params;
+ mServiceName = serviceName;
+ mUser = user;
+ mRecognitionConfig = config;
+ mHandler = new Handler(Looper.getMainLooper());
+
+ PowerManager pm = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE));
+ mRemoteServiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "RemoteSoundTriggerDetectionService " + mServiceName.getPackageName() + ":"
+ + mServiceName.getClassName());
+
+ synchronized (mLock) {
+ NumOps numOps = mNumOpsPerPackage.get(mServiceName.getPackageName());
+ if (numOps == null) {
+ numOps = new NumOps();
+ mNumOpsPerPackage.put(mServiceName.getPackageName(), numOps);
}
+ mNumOps = numOps;
}
- }
- }
- /**
- * Add a new operation.
- *
- * @param currentTime Current elapsed time since boot in ns
- */
- void addOp(long currentTime) {
- synchronized (mLock) {
- long numHoursSinceBoot = TimeUnit.HOURS.convert(currentTime, TimeUnit.NANOSECONDS);
-
- mNumOps[(int) (numHoursSinceBoot % 24)]++;
- mLastOpsHourSinceBoot = numHoursSinceBoot;
- }
- }
-
- /**
- * Get the total operations added in the last 24 hours.
- *
- * @return The total number of operations added in the last 24 hours
- */
- int getOpsAdded() {
- synchronized (mLock) {
- int totalOperationsInLastDay = 0;
- for (int i = 0; i < 24; i++) {
- totalOperationsInLastDay += mNumOps[i];
- }
-
- return totalOperationsInLastDay;
- }
- }
- }
-
- /**
- * A single operation run in a {@link RemoteSoundTriggerDetectionService}.
- *
- * <p>Once the remote service is connected either setup + execute or setup + stop is executed.
- */
- private static class Operation {
- private interface ExecuteOp {
- void run(int opId, ISoundTriggerDetectionService service) throws RemoteException;
- }
-
- private final @Nullable Runnable mSetupOp;
- private final @NonNull ExecuteOp mExecuteOp;
- private final @Nullable Runnable mDropOp;
-
- private Operation(@Nullable Runnable setupOp, @NonNull ExecuteOp executeOp,
- @Nullable Runnable cancelOp) {
- mSetupOp = setupOp;
- mExecuteOp = executeOp;
- mDropOp = cancelOp;
- }
-
- private void setup() {
- if (mSetupOp != null) {
- mSetupOp.run();
- }
- }
-
- void run(int opId, @NonNull ISoundTriggerDetectionService service) throws RemoteException {
- setup();
- mExecuteOp.run(opId, service);
- }
-
- void drop() {
- setup();
-
- if (mDropOp != null) {
- mDropOp.run();
- }
- }
- }
-
- /**
- * Local end for a {@link SoundTriggerDetectionService}. Operations are queued up and executed
- * when the service connects.
- *
- * <p>If operations take too long they are forcefully aborted.
- *
- * <p>This also limits the amount of operations in 24 hours.
- */
- private class RemoteSoundTriggerDetectionService
- extends IRecognitionStatusCallback.Stub implements ServiceConnection {
- private static final int MSG_STOP_ALL_PENDING_OPERATIONS = 1;
-
- private final Object mRemoteServiceLock = new Object();
-
- /** UUID of the model the service is started for */
- private final @NonNull ParcelUuid mPuuid;
- /** Params passed into the start method for the service */
- private final @Nullable Bundle mParams;
- /** Component name passed when starting the service */
- private final @NonNull ComponentName mServiceName;
- /** User that started the service */
- private final @NonNull UserHandle mUser;
- /** Configuration of the recognition the service is handling */
- private final @NonNull RecognitionConfig mRecognitionConfig;
- /** Wake lock keeping the remote service alive */
- private final @NonNull PowerManager.WakeLock mRemoteServiceWakeLock;
-
- private final @NonNull Handler mHandler;
-
- /** Callbacks that are called by the service */
- private final @NonNull ISoundTriggerDetectionServiceClient mClient;
-
- /** Operations that are pending because the service is not yet connected */
- @GuardedBy("mRemoteServiceLock")
- private final ArrayList<Operation> mPendingOps = new ArrayList<>();
- /** Operations that have been send to the service but have no yet finished */
- @GuardedBy("mRemoteServiceLock")
- private final ArraySet<Integer> mRunningOpIds = new ArraySet<>();
- /** The number of operations executed in each of the last 24 hours */
- private final NumOps mNumOps;
-
- /** The service binder if connected */
- @GuardedBy("mRemoteServiceLock")
- private @Nullable ISoundTriggerDetectionService mService;
- /** Whether the service has been bound */
- @GuardedBy("mRemoteServiceLock")
- private boolean mIsBound;
- /** Whether the service has been destroyed */
- @GuardedBy("mRemoteServiceLock")
- private boolean mIsDestroyed;
- /**
- * Set once a final op is scheduled. No further ops can be added and the service is
- * destroyed once the op finishes.
- */
- @GuardedBy("mRemoteServiceLock")
- private boolean mDestroyOnceRunningOpsDone;
-
- /** Total number of operations performed by this service */
- @GuardedBy("mRemoteServiceLock")
- private int mNumTotalOpsPerformed;
-
- /**
- * Create a new remote sound trigger detection service. This only binds to the service when
- * operations are in flight. Each operation has a certain time it can run. Once no
- * operations are allowed to run anymore, {@link #stopAllPendingOperations() all operations
- * are aborted and stopped} and the service is disconnected.
- *
- * @param modelUuid The UUID of the model the recognition is for
- * @param params The params passed to each method of the service
- * @param serviceName The component name of the service
- * @param user The user of the service
- * @param config The configuration of the recognition
- */
- public RemoteSoundTriggerDetectionService(@NonNull UUID modelUuid,
- @Nullable Bundle params, @NonNull ComponentName serviceName, @NonNull UserHandle user,
- @NonNull RecognitionConfig config) {
- mPuuid = new ParcelUuid(modelUuid);
- mParams = params;
- mServiceName = serviceName;
- mUser = user;
- mRecognitionConfig = config;
- mHandler = new Handler(Looper.getMainLooper());
-
- PowerManager pm = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE));
- mRemoteServiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- "RemoteSoundTriggerDetectionService " + mServiceName.getPackageName() + ":"
- + mServiceName.getClassName());
-
- synchronized (mLock) {
- NumOps numOps = mNumOpsPerPackage.get(mServiceName.getPackageName());
- if (numOps == null) {
- numOps = new NumOps();
- mNumOpsPerPackage.put(mServiceName.getPackageName(), numOps);
- }
- mNumOps = numOps;
- }
-
- mClient = new ISoundTriggerDetectionServiceClient.Stub() {
- @Override
- public void onOpFinished(int opId) {
- long token = Binder.clearCallingIdentity();
- try {
- synchronized (mRemoteServiceLock) {
- mRunningOpIds.remove(opId);
-
- if (mRunningOpIds.isEmpty() && mPendingOps.isEmpty()) {
- if (mDestroyOnceRunningOpsDone) {
- destroy();
- } else {
- disconnectLocked();
+ mClient = new ISoundTriggerDetectionServiceClient.Stub() {
+ @Override
+ public void onOpFinished(int opId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mRemoteServiceLock) {
+ mRunningOpIds.remove(opId);
+
+ if (mRunningOpIds.isEmpty() && mPendingOps.isEmpty()) {
+ if (mDestroyOnceRunningOpsDone) {
+ destroy();
+ } else {
+ disconnectLocked();
+ }
}
}
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
- }
- };
- }
+ };
+ }
- @Override
- public boolean pingBinder() {
- return !(mIsDestroyed || mDestroyOnceRunningOpsDone);
- }
+ @Override
+ public boolean pingBinder() {
+ return !(mIsDestroyed || mDestroyOnceRunningOpsDone);
+ }
- /**
- * Disconnect from the service, but allow to re-connect when new operations are triggered.
- */
- @GuardedBy("mRemoteServiceLock")
- private void disconnectLocked() {
- if (mService != null) {
- try {
- mService.removeClient(mPuuid);
- } catch (Exception e) {
- Slog.e(TAG, mPuuid + ": Cannot remove client", e);
+ /**
+ * Disconnect from the service, but allow to re-connect when new operations are
+ * triggered.
+ */
+ @GuardedBy("mRemoteServiceLock")
+ private void disconnectLocked() {
+ if (mService != null) {
+ try {
+ mService.removeClient(mPuuid);
+ } catch (Exception e) {
+ Slog.e(TAG, mPuuid + ": Cannot remove client", e);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": Cannot remove client"));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": Cannot remove client"));
- }
+ }
- mService = null;
- }
+ mService = null;
+ }
- if (mIsBound) {
- mContext.unbindService(RemoteSoundTriggerDetectionService.this);
- mIsBound = false;
+ if (mIsBound) {
+ mContext.unbindService(RemoteSoundTriggerDetectionService.this);
+ mIsBound = false;
- synchronized (mCallbacksLock) {
- mRemoteServiceWakeLock.release();
+ synchronized (mCallbacksLock) {
+ mRemoteServiceWakeLock.release();
+ }
}
}
- }
- /**
- * Disconnect, do not allow to reconnect to the service. All further operations will be
- * dropped.
- */
- private void destroy() {
- if (DEBUG) Slog.v(TAG, mPuuid + ": destroy");
+ /**
+ * Disconnect, do not allow to reconnect to the service. All further operations will be
+ * dropped.
+ */
+ private void destroy() {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": destroy");
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid + ": destroy"));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid + ": destroy"));
- synchronized (mRemoteServiceLock) {
- disconnectLocked();
+ synchronized (mRemoteServiceLock) {
+ disconnectLocked();
- mIsDestroyed = true;
- }
+ mIsDestroyed = true;
+ }
- // The callback is removed before the flag is set
- if (!mDestroyOnceRunningOpsDone) {
- synchronized (mCallbacksLock) {
- mCallbacks.remove(mPuuid.getUuid());
+ // The callback is removed before the flag is set
+ if (!mDestroyOnceRunningOpsDone) {
+ synchronized (mCallbacksLock) {
+ mCallbacks.remove(mPuuid.getUuid());
+ }
}
}
- }
- /**
- * Stop all pending operations and then disconnect for the service.
- */
- private void stopAllPendingOperations() {
- synchronized (mRemoteServiceLock) {
- if (mIsDestroyed) {
- return;
- }
+ /**
+ * Stop all pending operations and then disconnect for the service.
+ */
+ private void stopAllPendingOperations() {
+ synchronized (mRemoteServiceLock) {
+ if (mIsDestroyed) {
+ return;
+ }
- if (mService != null) {
- int numOps = mRunningOpIds.size();
- for (int i = 0; i < numOps; i++) {
- try {
- mService.onStopOperation(mPuuid, mRunningOpIds.valueAt(i));
- } catch (Exception e) {
- Slog.e(TAG, mPuuid + ": Could not stop operation "
- + mRunningOpIds.valueAt(i), e);
+ if (mService != null) {
+ int numOps = mRunningOpIds.size();
+ for (int i = 0; i < numOps; i++) {
+ try {
+ mService.onStopOperation(mPuuid, mRunningOpIds.valueAt(i));
+ } catch (Exception e) {
+ Slog.e(TAG, mPuuid + ": Could not stop operation "
+ + mRunningOpIds.valueAt(i), e);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": Could not stop operation " + mRunningOpIds.valueAt(i)));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": Could not stop operation " + mRunningOpIds.valueAt(
+ i)));
+ }
}
+
+ mRunningOpIds.clear();
}
- mRunningOpIds.clear();
+ disconnectLocked();
}
-
- disconnectLocked();
}
- }
- /**
- * Verify that the service has the expected properties and then bind to the service
- */
- private void bind() {
- long token = Binder.clearCallingIdentity();
- try {
- Intent i = new Intent();
- i.setComponent(mServiceName);
+ /**
+ * Verify that the service has the expected properties and then bind to the service
+ */
+ private void bind() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ Intent i = new Intent();
+ i.setComponent(mServiceName);
- ResolveInfo ri = mContext.getPackageManager().resolveServiceAsUser(i,
- GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING,
- mUser.getIdentifier());
+ ResolveInfo ri = mContext.getPackageManager().resolveServiceAsUser(i,
+ GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING,
+ mUser.getIdentifier());
- if (ri == null) {
- Slog.w(TAG, mPuuid + ": " + mServiceName + " not found");
+ if (ri == null) {
+ Slog.w(TAG, mPuuid + ": " + mServiceName + " not found");
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": " + mServiceName + " not found"));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": " + mServiceName + " not found"));
- return;
- }
+ return;
+ }
- if (!BIND_SOUND_TRIGGER_DETECTION_SERVICE
- .equals(ri.serviceInfo.permission)) {
- Slog.w(TAG, mPuuid + ": " + mServiceName + " does not require "
- + BIND_SOUND_TRIGGER_DETECTION_SERVICE);
+ if (!BIND_SOUND_TRIGGER_DETECTION_SERVICE
+ .equals(ri.serviceInfo.permission)) {
+ Slog.w(TAG, mPuuid + ": " + mServiceName + " does not require "
+ + BIND_SOUND_TRIGGER_DETECTION_SERVICE);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": " + mServiceName + " does not require "
- + BIND_SOUND_TRIGGER_DETECTION_SERVICE));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": " + mServiceName + " does not require "
+ + BIND_SOUND_TRIGGER_DETECTION_SERVICE));
- return;
- }
+ return;
+ }
- mIsBound = mContext.bindServiceAsUser(i, this,
- BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_INCLUDE_CAPABILITIES,
- mUser);
+ mIsBound = mContext.bindServiceAsUser(i, this,
+ BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_INCLUDE_CAPABILITIES,
+ mUser);
- if (mIsBound) {
- mRemoteServiceWakeLock.acquire();
- } else {
- Slog.w(TAG, mPuuid + ": Could not bind to " + mServiceName);
+ if (mIsBound) {
+ mRemoteServiceWakeLock.acquire();
+ } else {
+ Slog.w(TAG, mPuuid + ": Could not bind to " + mServiceName);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": Could not bind to " + mServiceName));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": Could not bind to " + mServiceName));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
- }
- /**
- * Run an operation (i.e. send it do the service). If the service is not connected, this
- * binds the service and then runs the operation once connected.
- *
- * @param op The operation to run
- */
- private void runOrAddOperation(Operation op) {
- synchronized (mRemoteServiceLock) {
- if (mIsDestroyed || mDestroyOnceRunningOpsDone) {
- Slog.w(TAG, mPuuid + ": Dropped operation as already destroyed or marked for "
- + "destruction");
+ /**
+ * Run an operation (i.e. send it do the service). If the service is not connected, this
+ * binds the service and then runs the operation once connected.
+ *
+ * @param op The operation to run
+ */
+ private void runOrAddOperation(Operation op) {
+ synchronized (mRemoteServiceLock) {
+ if (mIsDestroyed || mDestroyOnceRunningOpsDone) {
+ Slog.w(TAG,
+ mPuuid + ": Dropped operation as already destroyed or marked for "
+ + "destruction");
+
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ":Dropped operation as already destroyed or marked for "
+ + "destruction"));
+
+ op.drop();
+ return;
+ }
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ":Dropped operation as already destroyed or marked for destruction"));
+ if (mService == null) {
+ mPendingOps.add(op);
- op.drop();
- return;
- }
+ if (!mIsBound) {
+ bind();
+ }
+ } else {
+ long currentTime = System.nanoTime();
+ mNumOps.clearOldOps(currentTime);
- if (mService == null) {
- mPendingOps.add(op);
+ // Drop operation if too many were executed in the last 24 hours.
+ int opsAllowed = Settings.Global.getInt(mContext.getContentResolver(),
+ MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
+ Integer.MAX_VALUE);
- if (!mIsBound) {
- bind();
- }
- } else {
- long currentTime = System.nanoTime();
- mNumOps.clearOldOps(currentTime);
-
- // Drop operation if too many were executed in the last 24 hours.
- int opsAllowed = Settings.Global.getInt(mContext.getContentResolver(),
- MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
- Integer.MAX_VALUE);
-
- // As we currently cannot dropping an op safely, disable throttling
- int opsAdded = mNumOps.getOpsAdded();
- if (false && mNumOps.getOpsAdded() >= opsAllowed) {
- try {
- if (DEBUG || opsAllowed + 10 > opsAdded) {
- Slog.w(TAG, mPuuid + ": Dropped operation as too many operations "
- + "were run in last 24 hours");
+ // As we currently cannot dropping an op safely, disable throttling
+ int opsAdded = mNumOps.getOpsAdded();
+ if (false && mNumOps.getOpsAdded() >= opsAllowed) {
+ try {
+ if (DEBUG || opsAllowed + 10 > opsAdded) {
+ Slog.w(TAG,
+ mPuuid + ": Dropped operation as too many operations "
+ + "were run in last 24 hours");
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": Dropped operation as too many operations "
- + "were run in last 24 hours"));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": Dropped operation as too many operations "
+ + "were run in last 24 hours"));
- }
+ }
- op.drop();
- } catch (Exception e) {
- Slog.e(TAG, mPuuid + ": Could not drop operation", e);
+ op.drop();
+ } catch (Exception e) {
+ Slog.e(TAG, mPuuid + ": Could not drop operation", e);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ ": Could not drop operation"));
- }
- } else {
- mNumOps.addOp(currentTime);
+ }
+ } else {
+ mNumOps.addOp(currentTime);
- // Find a free opID
- int opId = mNumTotalOpsPerformed;
- do {
- mNumTotalOpsPerformed++;
- } while (mRunningOpIds.contains(opId));
+ // Find a free opID
+ int opId = mNumTotalOpsPerformed;
+ do {
+ mNumTotalOpsPerformed++;
+ } while (mRunningOpIds.contains(opId));
- // Run OP
- try {
- if (DEBUG) Slog.v(TAG, mPuuid + ": runOp " + opId);
+ // Run OP
+ try {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": runOp " + opId);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ ": runOp " + opId));
- op.run(opId, mService);
- mRunningOpIds.add(opId);
- } catch (Exception e) {
- Slog.e(TAG, mPuuid + ": Could not run operation " + opId, e);
+ op.run(opId, mService);
+ mRunningOpIds.add(opId);
+ } catch (Exception e) {
+ Slog.e(TAG, mPuuid + ": Could not run operation " + opId, e);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ ": Could not run operation " + opId));
+ }
}
- }
- // Unbind from service if no operations are left (i.e. if the operation failed)
- if (mPendingOps.isEmpty() && mRunningOpIds.isEmpty()) {
- if (mDestroyOnceRunningOpsDone) {
- destroy();
+ // Unbind from service if no operations are left (i.e. if the operation
+ // failed)
+ if (mPendingOps.isEmpty() && mRunningOpIds.isEmpty()) {
+ if (mDestroyOnceRunningOpsDone) {
+ destroy();
+ } else {
+ disconnectLocked();
+ }
} else {
- disconnectLocked();
+ mHandler.removeMessages(MSG_STOP_ALL_PENDING_OPERATIONS);
+ mHandler.sendMessageDelayed(obtainMessage(
+ RemoteSoundTriggerDetectionService::stopAllPendingOperations,
+ this)
+ .setWhat(MSG_STOP_ALL_PENDING_OPERATIONS),
+ Settings.Global.getLong(mContext.getContentResolver(),
+ SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT,
+ Long.MAX_VALUE));
}
- } else {
- mHandler.removeMessages(MSG_STOP_ALL_PENDING_OPERATIONS);
- mHandler.sendMessageDelayed(obtainMessage(
- RemoteSoundTriggerDetectionService::stopAllPendingOperations, this)
- .setWhat(MSG_STOP_ALL_PENDING_OPERATIONS),
- Settings.Global.getLong(mContext.getContentResolver(),
- SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT,
- Long.MAX_VALUE));
}
}
}
- }
-
- @Override
- public void onKeyphraseDetected(SoundTrigger.KeyphraseRecognitionEvent event) {
- Slog.w(TAG, mPuuid + "->" + mServiceName + ": IGNORED onKeyphraseDetected(" + event
- + ")");
-
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid + "->" + mServiceName
- + ": IGNORED onKeyphraseDetected(" + event + ")"));
- }
+ @Override
+ public void onKeyphraseDetected(SoundTrigger.KeyphraseRecognitionEvent event) {
+ Slog.w(TAG, mPuuid + "->" + mServiceName + ": IGNORED onKeyphraseDetected(" + event
+ + ")");
- /**
- * Create an AudioRecord enough for starting and releasing the data buffered for the event.
- *
- * @param event The event that was received
- * @return The initialized AudioRecord
- */
- private @NonNull AudioRecord createAudioRecordForEvent(
- @NonNull SoundTrigger.GenericRecognitionEvent event)
- throws IllegalArgumentException, UnsupportedOperationException {
- AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder();
- attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD);
- AudioAttributes attributes = attributesBuilder.build();
-
- AudioFormat originalFormat = event.getCaptureFormat();
-
- sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent"));
-
- return (new AudioRecord.Builder())
- .setAudioAttributes(attributes)
- .setAudioFormat((new AudioFormat.Builder())
- .setChannelMask(originalFormat.getChannelMask())
- .setEncoding(originalFormat.getEncoding())
- .setSampleRate(originalFormat.getSampleRate())
- .build())
- .setSessionId(event.getCaptureSession())
- .build();
- }
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid + "->" + mServiceName
+ + ": IGNORED onKeyphraseDetected(" + event + ")"));
+ }
- @Override
- public void onGenericSoundTriggerDetected(SoundTrigger.GenericRecognitionEvent event) {
- if (DEBUG) Slog.v(TAG, mPuuid + ": Generic sound trigger event: " + event);
-
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": Generic sound trigger event: " + event));
-
- runOrAddOperation(new Operation(
- // always execute:
- () -> {
- if (!mRecognitionConfig.allowMultipleTriggers) {
- // Unregister this remoteService once op is done
- synchronized (mCallbacksLock) {
- mCallbacks.remove(mPuuid.getUuid());
- }
- mDestroyOnceRunningOpsDone = true;
- }
- },
- // execute if not throttled:
- (opId, service) -> service.onGenericRecognitionEvent(mPuuid, opId, event),
- // execute if throttled:
- () -> {
- if (event.isCaptureAvailable()) {
- try {
- AudioRecord capturedData = createAudioRecordForEvent(event);
- capturedData.startRecording();
- capturedData.release();
- } catch (IllegalArgumentException | UnsupportedOperationException e) {
- Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event
- + "), failed to create AudioRecord");
- }
- }
- }));
- }
+ /**
+ * Create an AudioRecord enough for starting and releasing the data buffered for the event.
+ *
+ * @param event The event that was received
+ * @return The initialized AudioRecord
+ */
+ private @NonNull AudioRecord createAudioRecordForEvent(
+ @NonNull SoundTrigger.GenericRecognitionEvent event)
+ throws IllegalArgumentException, UnsupportedOperationException {
+ AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder();
+ attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD);
+ AudioAttributes attributes = attributesBuilder.build();
+
+ AudioFormat originalFormat = event.getCaptureFormat();
+
+ sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent"));
+
+ 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
- public void onError(int status) {
- if (DEBUG) Slog.v(TAG, mPuuid + ": onError: " + status);
+ @Override
+ public void onGenericSoundTriggerDetected(SoundTrigger.GenericRecognitionEvent event) {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": Generic sound trigger event: " + event);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": onError: " + status));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": Generic sound trigger event: " + event));
- runOrAddOperation(
- new Operation(
- // always execute:
- () -> {
+ runOrAddOperation(new Operation(
+ // always execute:
+ () -> {
+ if (!mRecognitionConfig.allowMultipleTriggers) {
// Unregister this remoteService once op is done
synchronized (mCallbacksLock) {
mCallbacks.remove(mPuuid.getUuid());
}
mDestroyOnceRunningOpsDone = true;
- },
- // execute if not throttled:
- (opId, service) -> service.onError(mPuuid, opId, status),
- // nothing to do if throttled
- null));
- }
+ }
+ },
+ // execute if not throttled:
+ (opId, service) -> service.onGenericRecognitionEvent(mPuuid, opId, event),
+ // execute if throttled:
+ () -> {
+ if (event.isCaptureAvailable()) {
+ try {
+ AudioRecord capturedData = createAudioRecordForEvent(event);
+ capturedData.startRecording();
+ capturedData.release();
+ } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event
+ + "), failed to create AudioRecord");
+ }
+ }
+ }));
+ }
- @Override
- public void onRecognitionPaused() {
- Slog.i(TAG, mPuuid + "->" + mServiceName + ": IGNORED onRecognitionPaused");
+ @Override
+ public void onError(int status) {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": onError: " + status);
+
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": onError: " + status));
+
+ runOrAddOperation(
+ new Operation(
+ // always execute:
+ () -> {
+ // Unregister this remoteService once op is done
+ synchronized (mCallbacksLock) {
+ mCallbacks.remove(mPuuid.getUuid());
+ }
+ mDestroyOnceRunningOpsDone = true;
+ },
+ // execute if not throttled:
+ (opId, service) -> service.onError(mPuuid, opId, status),
+ // nothing to do if throttled
+ null));
+ }
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + "->" + mServiceName + ": IGNORED onRecognitionPaused"));
+ @Override
+ public void onRecognitionPaused() {
+ Slog.i(TAG, mPuuid + "->" + mServiceName + ": IGNORED onRecognitionPaused");
- }
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + "->" + mServiceName + ": IGNORED onRecognitionPaused"));
- @Override
- public void onRecognitionResumed() {
- Slog.i(TAG, mPuuid + "->" + mServiceName + ": IGNORED onRecognitionResumed");
+ }
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + "->" + mServiceName + ": IGNORED onRecognitionResumed"));
+ @Override
+ public void onRecognitionResumed() {
+ Slog.i(TAG, mPuuid + "->" + mServiceName + ": IGNORED onRecognitionResumed");
- }
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + "->" + mServiceName + ": IGNORED onRecognitionResumed"));
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG) Slog.v(TAG, mPuuid + ": onServiceConnected(" + service + ")");
+ }
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": onServiceConnected(" + service + ")"));
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": onServiceConnected(" + service + ")");
- synchronized (mRemoteServiceLock) {
- mService = ISoundTriggerDetectionService.Stub.asInterface(service);
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": onServiceConnected(" + service + ")"));
- try {
- mService.setClient(mPuuid, mParams, mClient);
- } catch (Exception e) {
- Slog.e(TAG, mPuuid + ": Could not init " + mServiceName, e);
- return;
+ synchronized (mRemoteServiceLock) {
+ mService = ISoundTriggerDetectionService.Stub.asInterface(service);
+
+ try {
+ mService.setClient(mPuuid, mParams, mClient);
+ } catch (Exception e) {
+ Slog.e(TAG, mPuuid + ": Could not init " + mServiceName, e);
+ return;
+ }
+
+ while (!mPendingOps.isEmpty()) {
+ runOrAddOperation(mPendingOps.remove(0));
+ }
}
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": onServiceDisconnected");
- while (!mPendingOps.isEmpty()) {
- runOrAddOperation(mPendingOps.remove(0));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": onServiceDisconnected"));
+
+ synchronized (mRemoteServiceLock) {
+ mService = null;
}
}
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- if (DEBUG) Slog.v(TAG, mPuuid + ": onServiceDisconnected");
+ @Override
+ public void onBindingDied(ComponentName name) {
+ if (DEBUG) Slog.v(TAG, mPuuid + ": onBindingDied");
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": onServiceDisconnected"));
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
+ + ": onBindingDied"));
- synchronized (mRemoteServiceLock) {
- mService = null;
+ synchronized (mRemoteServiceLock) {
+ destroy();
+ }
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ Slog.w(TAG, name + " for model " + mPuuid + " returned a null binding");
+
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(name + " for model "
+ + mPuuid + " returned a null binding"));
+
+ synchronized (mRemoteServiceLock) {
+ disconnectLocked();
+ }
}
}
+ }
- @Override
- public void onBindingDied(ComponentName name) {
- if (DEBUG) Slog.v(TAG, mPuuid + ": onBindingDied");
+ /**
+ * Counts the number of operations added in the last 24 hours.
+ */
+ private static class NumOps {
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private int[] mNumOps = new int[24];
+ @GuardedBy("mLock")
+ private long mLastOpsHourSinceBoot;
- sEventLogger.log(new SoundTriggerLogger.StringEvent(mPuuid
- + ": onBindingDied"));
+ /**
+ * Clear buckets of new hours that have elapsed since last operation.
+ *
+ * <p>I.e. when the last operation was triggered at 1:40 and the current operation was
+ * triggered at 4:03, the buckets "2, 3, and 4" are cleared.
+ *
+ * @param currentTime Current elapsed time since boot in ns
+ */
+ void clearOldOps(long currentTime) {
+ synchronized (mLock) {
+ long numHoursSinceBoot = TimeUnit.HOURS.convert(currentTime, TimeUnit.NANOSECONDS);
- synchronized (mRemoteServiceLock) {
- destroy();
+ // Clear buckets of new hours that have elapsed since last operation
+ // I.e. when the last operation was triggered at 1:40 and the current
+ // operation was triggered at 4:03, the bucket "2, 3, and 4" is cleared
+ if (mLastOpsHourSinceBoot != 0) {
+ for (long hour = mLastOpsHourSinceBoot + 1; hour <= numHoursSinceBoot; hour++) {
+ mNumOps[(int) (hour % 24)] = 0;
+ }
+ }
}
}
- @Override
- public void onNullBinding(ComponentName name) {
- Slog.w(TAG, name + " for model " + mPuuid + " returned a null binding");
+ /**
+ * Add a new operation.
+ *
+ * @param currentTime Current elapsed time since boot in ns
+ */
+ void addOp(long currentTime) {
+ synchronized (mLock) {
+ long numHoursSinceBoot = TimeUnit.HOURS.convert(currentTime, TimeUnit.NANOSECONDS);
- sEventLogger.log(new SoundTriggerLogger.StringEvent(name + " for model "
- + mPuuid + " returned a null binding"));
+ mNumOps[(int) (numHoursSinceBoot % 24)]++;
+ mLastOpsHourSinceBoot = numHoursSinceBoot;
+ }
+ }
- synchronized (mRemoteServiceLock) {
- disconnectLocked();
+ /**
+ * Get the total operations added in the last 24 hours.
+ *
+ * @return The total number of operations added in the last 24 hours
+ */
+ int getOpsAdded() {
+ synchronized (mLock) {
+ int totalOperationsInLastDay = 0;
+ for (int i = 0; i < 24; i++) {
+ totalOperationsInLastDay += mNumOps[i];
+ }
+
+ return totalOperationsInLastDay;
}
}
}
- public final class LocalSoundTriggerService extends SoundTriggerInternal {
- private final Context mContext;
- private SoundTriggerHelper mSoundTriggerHelper;
-
- LocalSoundTriggerService(Context context) {
- mContext = context;
+ /**
+ * A single operation run in a {@link RemoteSoundTriggerDetectionService}.
+ *
+ * <p>Once the remote service is connected either setup + execute or setup + stop is executed.
+ */
+ private static class Operation {
+ private interface ExecuteOp {
+ void run(int opId, ISoundTriggerDetectionService service) throws RemoteException;
}
- synchronized void setSoundTriggerHelper(SoundTriggerHelper helper) {
- mSoundTriggerHelper = helper;
+ private final @Nullable Runnable mSetupOp;
+ private final @NonNull ExecuteOp mExecuteOp;
+ private final @Nullable Runnable mDropOp;
+
+ private Operation(@Nullable Runnable setupOp, @NonNull ExecuteOp executeOp,
+ @Nullable Runnable cancelOp) {
+ mSetupOp = setupOp;
+ mExecuteOp = executeOp;
+ mDropOp = cancelOp;
}
- @Override
- public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
- IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.startKeyphraseRecognition(keyphraseId, soundModel, listener,
- recognitionConfig);
+ private void setup() {
+ if (mSetupOp != null) {
+ mSetupOp.run();
+ }
}
- @Override
- public synchronized int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.stopKeyphraseRecognition(keyphraseId, listener);
+ void run(int opId, @NonNull ISoundTriggerDetectionService service) throws RemoteException {
+ setup();
+ mExecuteOp.run(opId, service);
}
- @Override
- public ModuleProperties getModuleProperties() {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.getModuleProperties();
+ void drop() {
+ setup();
+
+ if (mDropOp != null) {
+ mDropOp.run();
+ }
}
+ }
- @Override
- public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.setKeyphraseParameter(keyphraseId, modelParam, value);
+ public final class LocalSoundTriggerService implements SoundTriggerInternal {
+ private final Context mContext;
+ LocalSoundTriggerService(Context context) {
+ mContext = context;
}
- @Override
- public int getParameter(int keyphraseId, @ModelParams int modelParam) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.getKeyphraseParameter(keyphraseId, modelParam);
+ private class SessionImpl implements Session {
+ private final @NonNull SoundTriggerHelper mSoundTriggerHelper;
+
+ private SessionImpl(
+ @NonNull SoundTriggerHelper soundTriggerHelper) {
+ mSoundTriggerHelper = soundTriggerHelper;
+ }
+
+ @Override
+ public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) {
+ return mSoundTriggerHelper.startKeyphraseRecognition(keyphraseId, soundModel,
+ listener,
+ recognitionConfig);
+ }
+
+ @Override
+ public synchronized int stopRecognition(int keyphraseId,
+ IRecognitionStatusCallback listener) {
+ return mSoundTriggerHelper.stopKeyphraseRecognition(keyphraseId, listener);
+ }
+
+ @Override
+ public ModuleProperties getModuleProperties() {
+ return mSoundTriggerHelper.getModuleProperties();
+ }
+
+ @Override
+ public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
+ return mSoundTriggerHelper.setKeyphraseParameter(keyphraseId, modelParam, value);
+ }
+
+ @Override
+ public int getParameter(int keyphraseId, @ModelParams int modelParam) {
+ return mSoundTriggerHelper.getKeyphraseParameter(keyphraseId, modelParam);
+ }
+
+ @Override
+ @Nullable
+ public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
+ return mSoundTriggerHelper.queryKeyphraseParameter(keyphraseId, modelParam);
+ }
+
+ @Override
+ public int unloadKeyphraseModel(int keyphraseId) {
+ return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mSoundTriggerHelper.dump(fd, pw, args);
+ }
}
@Override
- @Nullable
- public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.queryKeyphraseParameter(keyphraseId, modelParam);
+ public Session attachAsOriginator(@NonNull Identity originatorIdentity) {
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
+ originatorIdentity)) {
+ return new SessionImpl(newSoundTriggerHelper());
+ }
}
@Override
- public int unloadKeyphraseModel(int keyphraseId) {
- if (!isInitialized()) throw new UnsupportedOperationException();
- return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
+ public Session attachAsMiddleman(@NonNull Identity middlemanIdentity,
+ @NonNull Identity originatorIdentity) {
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityIndirect(mContext,
+ SOUNDTRIGGER_DELEGATE_IDENTITY, middlemanIdentity, originatorIdentity)) {
+ return new SessionImpl(newSoundTriggerHelper());
+ }
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (!isInitialized()) return;
- mSoundTriggerHelper.dump(fd, pw, args);
// log
sEventLogger.dump(pw);
@@ -1503,18 +1537,6 @@ public class SoundTriggerService extends SystemService {
// stats
mSoundModelStatTracker.dump(pw);
}
-
- private synchronized boolean isInitialized() {
- if (mSoundTriggerHelper == null ) {
- Slog.e(TAG, "SoundTriggerHelper not initialized.");
-
- sEventLogger.log(new SoundTriggerLogger.StringEvent(
- "SoundTriggerHelper not initialized."));
-
- return false;
- }
- return true;
- }
}
private void enforceCallingPermission(String permission) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index a2215ceed36a..f4fc185d3b5c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
@@ -48,6 +49,11 @@ import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.Identity;
+import android.media.permission.IdentityContext;
+import android.media.permission.PermissionUtil;
+import android.media.permission.SafeCloseable;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -69,6 +75,7 @@ import android.service.voice.VoiceInteractionServiceInfo;
import android.service.voice.VoiceInteractionSession;
import android.speech.RecognitionService;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -78,6 +85,7 @@ import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionManagerService;
import com.android.internal.app.IVoiceInteractionSessionListener;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
@@ -93,7 +101,10 @@ import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -111,7 +122,8 @@ public class VoiceInteractionManagerService extends SystemService {
final ActivityManagerInternal mAmInternal;
final ActivityTaskManagerInternal mAtmInternal;
final UserManagerInternal mUserManagerInternal;
- final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>();
+ final ArrayMap<Integer, VoiceInteractionManagerServiceStub.SoundTriggerSession>
+ mLoadedKeyphraseIds = new ArrayMap<>();
ShortcutServiceInternal mShortcutServiceInternal;
SoundTriggerInternal mSoundTriggerInternal;
@@ -236,12 +248,28 @@ public class VoiceInteractionManagerService extends SystemService {
private boolean mTemporarilyDisabled;
private final boolean mEnableService;
+ private final List<WeakReference<SoundTriggerSession>> mSessions = new LinkedList<>();
VoiceInteractionManagerServiceStub() {
mEnableService = shouldEnableService(mContext);
new RoleObserver(mContext.getMainExecutor());
}
+ @Override
+ public @NonNull IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
+ @NonNull Identity originatorIdentity) {
+ Objects.requireNonNull(originatorIdentity);
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
+ originatorIdentity)) {
+ SoundTriggerSession session = new SoundTriggerSession(
+ mSoundTriggerInternal.attachAsOriginator(IdentityContext.getNonNull()));
+ synchronized (mSessions) {
+ mSessions.add(new WeakReference<>(session));
+ }
+ return session;
+ }
+ }
+
// TODO: VI Make sure the caller is the current user or profile
void startLocalVoiceInteraction(final IBinder token, Bundle options) {
if (mImpl == null) return;
@@ -1014,12 +1042,15 @@ public class VoiceInteractionManagerService extends SystemService {
final long caller = Binder.clearCallingIdentity();
boolean deleted = false;
try {
- int unloadStatus = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
- if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
- Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
+ SoundTriggerSession session = mLoadedKeyphraseIds.get(keyphraseId);
+ if (session != null) {
+ int unloadStatus = session.unloadKeyphraseModel(keyphraseId);
+ if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
+ Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
+ }
+ deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUserId,
+ bcp47Locale);
}
- deleted = mDbHelper.deleteKeyphraseSoundModel(
- keyphraseId, callingUserId, bcp47Locale);
return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
} finally {
if (deleted) {
@@ -1092,132 +1123,145 @@ public class VoiceInteractionManagerService extends SystemService {
return null;
}
- @Override
- public ModuleProperties getDspModuleProperties() {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ class SoundTriggerSession extends IVoiceInteractionSoundTriggerSession.Stub {
+ final SoundTriggerInternal.Session mSession;
- final long caller = Binder.clearCallingIdentity();
- try {
- return mSoundTriggerInternal.getModuleProperties();
- } finally {
- Binder.restoreCallingIdentity(caller);
- }
+ SoundTriggerSession(
+ SoundTriggerInternal.Session session) {
+ mSession = session;
}
- }
- @Override
- public int startRecognition(int keyphraseId, String bcp47Locale,
- IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ @Override
+ public ModuleProperties getDspModuleProperties() {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
- if (callback == null || recognitionConfig == null || bcp47Locale == null) {
- throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mSession.getModuleProperties();
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
}
- final int callingUserId = UserHandle.getCallingUserId();
- final long caller = Binder.clearCallingIdentity();
- try {
- KeyphraseSoundModel soundModel =
- mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
- if (soundModel == null
- || soundModel.getUuid() == null
- || soundModel.getKeyphrases() == null) {
- Slog.w(TAG, "No matching sound model found in startRecognition");
- return SoundTriggerInternal.STATUS_ERROR;
- } else {
- // Regardless of the status of the start recognition, we need to make sure
- // that we unload this model if needed later.
- synchronized (this) {
- mLoadedKeyphraseIds.add(keyphraseId);
+ @Override
+ public int startRecognition(int keyphraseId, String bcp47Locale,
+ IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
+
+ if (callback == null || recognitionConfig == null || bcp47Locale == null) {
+ throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
}
- return mSoundTriggerInternal.startRecognition(
- keyphraseId, soundModel, callback, recognitionConfig);
}
- } finally {
- Binder.restoreCallingIdentity(caller);
- }
- }
- @Override
- public int stopRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ final int callingUserId = UserHandle.getCallingUserId();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ KeyphraseSoundModel soundModel =
+ mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
+ if (soundModel == null
+ || soundModel.getUuid() == null
+ || soundModel.getKeyphrases() == null) {
+ Slog.w(TAG, "No matching sound model found in startRecognition");
+ return SoundTriggerInternal.STATUS_ERROR;
+ } else {
+ // Regardless of the status of the start recognition, we need to make sure
+ // that we unload this model if needed later.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ mLoadedKeyphraseIds.put(keyphraseId, this);
+ }
+ return mSession.startRecognition(
+ keyphraseId, soundModel, callback, recognitionConfig);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
- final long caller = Binder.clearCallingIdentity();
- try {
- return mSoundTriggerInternal.stopRecognition(keyphraseId, callback);
- } finally {
- Binder.restoreCallingIdentity(caller);
- }
- }
+ @Override
+ public int stopRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
+ }
- @Override
- public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mSession.stopRecognition(keyphraseId, callback);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
- final long caller = Binder.clearCallingIdentity();
- try {
- return mSoundTriggerInternal.setParameter(keyphraseId, modelParam, value);
- } finally {
- Binder.restoreCallingIdentity(caller);
- }
- }
+ @Override
+ public int setParameter(int keyphraseId, @ModelParams int modelParam, int value) {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
+ }
- @Override
- public int getParameter(int keyphraseId, @ModelParams int modelParam) {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mSession.setParameter(keyphraseId, modelParam, value);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
- final long caller = Binder.clearCallingIdentity();
- try {
- return mSoundTriggerInternal.getParameter(keyphraseId, modelParam);
- } finally {
- Binder.restoreCallingIdentity(caller);
- }
- }
+ @Override
+ public int getParameter(int keyphraseId, @ModelParams int modelParam) {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
+ }
- @Override
- @Nullable
- public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
- // Allow the call if this is the current voice interaction service.
- synchronized (this) {
- enforceIsCurrentVoiceInteractionService();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mSession.getParameter(keyphraseId, modelParam);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
- final long caller = Binder.clearCallingIdentity();
- try {
- return mSoundTriggerInternal.queryParameter(keyphraseId, modelParam);
- } finally {
- Binder.restoreCallingIdentity(caller);
+ @Override
+ @Nullable
+ public ModelParamRange queryParameter(int keyphraseId, @ModelParams int modelParam) {
+ // Allow the call if this is the current voice interaction service.
+ synchronized (VoiceInteractionManagerServiceStub.this) {
+ enforceIsCurrentVoiceInteractionService();
+ }
+
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mSession.queryParameter(keyphraseId, modelParam);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
}
- }
- private synchronized void unloadAllKeyphraseModels() {
- for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) {
+ private int unloadKeyphraseModel(int keyphraseId) {
final long caller = Binder.clearCallingIdentity();
try {
- int status = mSoundTriggerInternal.unloadKeyphraseModel(
- mLoadedKeyphraseIds.valueAt(i));
- if (status != SoundTriggerInternal.STATUS_OK) {
- Slog.w(TAG, "Failed to unload keyphrase " + mLoadedKeyphraseIds.valueAt(i)
- + ":" + status);
- }
+ return mSession.unloadKeyphraseModel(keyphraseId);
} finally {
Binder.restoreCallingIdentity(caller);
}
}
+ }
+
+ private synchronized void unloadAllKeyphraseModels() {
+ for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) {
+ int id = mLoadedKeyphraseIds.keyAt(i);
+ SoundTriggerSession session = mLoadedKeyphraseIds.valueAt(i);
+ int status = session.unloadKeyphraseModel(id);
+ if (status != SoundTriggerInternal.STATUS_OK) {
+ Slog.w(TAG, "Failed to unload keyphrase " + id + ":" + status);
+ }
+ }
mLoadedKeyphraseIds.clear();
}
@@ -1420,7 +1464,24 @@ public class VoiceInteractionManagerService extends SystemService {
mImpl.dumpLocked(fd, pw, args);
}
}
+
mSoundTriggerInternal.dump(fd, pw, args);
+
+ // Dump all sessions.
+ synchronized (mSessions) {
+ ListIterator<WeakReference<SoundTriggerSession>> iter =
+ mSessions.listIterator();
+ while (iter.hasNext()) {
+ SoundTriggerSession session = iter.next().get();
+ if (session != null) {
+ session.dump(fd, args);
+ } else {
+ // Session is obsolete, now is a good chance to remove it from the list.
+ iter.remove();
+ }
+ }
+ }
+
}
@Override
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index ec8e8e7910e8..0a7e1581815e 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -27,6 +27,26 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
+ public final class CallForwardingInfo implements android.os.Parcelable {
+ ctor public CallForwardingInfo(boolean, int, @Nullable String, int);
+ method public int describeContents();
+ method @Nullable public String getNumber();
+ method public int getReason();
+ method public int getTimeoutSeconds();
+ method public boolean isEnabled();
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
+ field public static final int ERROR_FDN_CHECK_FAILURE = 2; // 0x2
+ field public static final int ERROR_NOT_SUPPORTED = 3; // 0x3
+ field public static final int ERROR_UNKNOWN = 1; // 0x1
+ field public static final int REASON_ALL = 4; // 0x4
+ field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int REASON_BUSY = 1; // 0x1
+ field public static final int REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int REASON_NO_REPLY = 2; // 0x2
+ field public static final int REASON_UNCONDITIONAL = 0; // 0x0
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -656,6 +676,8 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -732,6 +754,8 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingStatus(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -769,6 +793,10 @@ package android.telephony {
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
+ field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
+ field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
+ field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -823,6 +851,11 @@ package android.telephony {
field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
}
+ public static interface TelephonyManager.CallForwardingInfoCallback {
+ method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo);
+ method public void onError(int);
+ }
+
public final class UiccAccessRule implements android.os.Parcelable {
ctor public UiccAccessRule(byte[], @Nullable String, long);
method public int describeContents();
diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java
index 7e777fae46eb..2106f7fc4bb8 100644
--- a/telephony/java/android/telephony/CallForwardingInfo.java
+++ b/telephony/java/android/telephony/CallForwardingInfo.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,50 +34,35 @@ import java.util.Objects;
* Defines the call forwarding information.
* @hide
*/
+@SystemApi
public final class CallForwardingInfo implements Parcelable {
private static final String TAG = "CallForwardingInfo";
/**
- * Indicates the call forwarding status is inactive.
- *
- * @hide
+ * Indicates that the operation was successful.
*/
- public static final int STATUS_INACTIVE = 0;
+ public static final int SUCCESS = 0;
/**
- * Indicates the call forwarding status is active.
- *
- * @hide
+ * Indicates that setting or retrieving the call forwarding info failed with an unknown error.
*/
- public static final int STATUS_ACTIVE = 1;
+ public static final int ERROR_UNKNOWN = 1;
/**
- * Indicates the call forwarding could not be enabled because the recipient is not on
+ * Indicates that call forwarding is not enabled because the recipient is not on a
* Fixed Dialing Number (FDN) list.
- *
- * @hide
*/
- public static final int STATUS_FDN_CHECK_FAILURE = 2;
+ public static final int ERROR_FDN_CHECK_FAILURE = 2;
/**
- * Indicates the call forwarding status is with an unknown error.
- *
- * @hide
+ * Indicates that call forwarding is not supported on the network at this time.
*/
- public static final int STATUS_UNKNOWN_ERROR = 3;
+ public static final int ERROR_NOT_SUPPORTED = 3;
/**
- * Indicates the call forwarding is not supported (e.g. called via CDMA).
- *
- * @hide
- */
- public static final int STATUS_NOT_SUPPORTED = 4;
-
- /**
- * Indicates the call forwarding reason is "unconditional".
+ * Indicates that call forwarding reason is "unconditional".
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_UNCONDITIONAL = 0;
@@ -84,7 +70,6 @@ public final class CallForwardingInfo implements Parcelable {
* Indicates the call forwarding status is "busy".
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_BUSY = 1;
@@ -92,7 +77,6 @@ public final class CallForwardingInfo implements Parcelable {
* Indicates the call forwarding reason is "no reply".
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_NO_REPLY = 2;
@@ -100,7 +84,6 @@ public final class CallForwardingInfo implements Parcelable {
* Indicates the call forwarding reason is "not reachable".
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_NOT_REACHABLE = 3;
@@ -109,7 +92,6 @@ public final class CallForwardingInfo implements Parcelable {
* simultaneously (unconditional, busy, no reply, and not reachable).
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_ALL = 4;
@@ -118,26 +100,25 @@ public final class CallForwardingInfo implements Parcelable {
* forwarding reasons simultaneously (busy, no reply, and not reachable).
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
- * @hide
*/
public static final int REASON_ALL_CONDITIONAL = 5;
/**
- * Call forwarding function status
+ * Call forwarding errors
+ * @hide
*/
- @IntDef(prefix = { "STATUS_" }, value = {
- STATUS_ACTIVE,
- STATUS_INACTIVE,
- STATUS_UNKNOWN_ERROR,
- STATUS_NOT_SUPPORTED,
- STATUS_FDN_CHECK_FAILURE
+ @IntDef(prefix = { "ERROR_" }, value = {
+ ERROR_UNKNOWN,
+ ERROR_NOT_SUPPORTED,
+ ERROR_FDN_CHECK_FAILURE
})
@Retention(RetentionPolicy.SOURCE)
- public @interface CallForwardingStatus {
+ public @interface CallForwardingError{
}
/**
* Call forwarding reason types
+ * @hide
*/
@IntDef(flag = true, prefix = { "REASON_" }, value = {
REASON_UNCONDITIONAL,
@@ -152,9 +133,9 @@ public final class CallForwardingInfo implements Parcelable {
}
/**
- * The call forwarding status.
+ * Whether call forwarding is enabled for this reason.
*/
- private int mStatus;
+ private boolean mEnabled;
/**
* The call forwarding reason indicates the condition under which calls will be forwarded.
@@ -178,39 +159,35 @@ public final class CallForwardingInfo implements Parcelable {
/**
* Construct a CallForwardingInfo.
*
- * @param status the call forwarding status
+ * @param enabled Whether to enable call forwarding for the reason specified
+ * in {@link #getReason()}.
* @param reason the call forwarding reason
* @param number the phone number to which calls will be forwarded
* @param timeSeconds the timeout (in seconds) before the forwarding is attempted
- * @hide
*/
- public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason,
+ public CallForwardingInfo(boolean enabled, @CallForwardingReason int reason,
@Nullable String number, int timeSeconds) {
- mStatus = status;
+ mEnabled = enabled;
mReason = reason;
mNumber = number;
mTimeSeconds = timeSeconds;
}
/**
- * Returns the call forwarding status.
- *
- * @return the call forwarding status.
+ * Whether call forwarding is enabled for the reason from {@link #getReason()}.
*
- * @hide
+ * @return {@code true} if enabled, {@code false} otherwise.
*/
- public @CallForwardingStatus int getStatus() {
- return mStatus;
+ public boolean isEnabled() {
+ return mEnabled;
}
/**
* Returns the call forwarding reason. The call forwarding reason indicates the condition
- * under which calls will be forwarded. For example, {@link #REASON_NO_REPLY} indicates
- * that calls will be forward to {@link #getNumber()} when the user fails to answer the call.
+ * under which calls will be forwarded. For example, {@link #REASON_NO_REPLY} indicates
+ * that calls will be forwarded when the user fails to answer the call.
*
* @return the call forwarding reason.
- *
- * @hide
*/
public @CallForwardingReason int getReason() {
return mReason;
@@ -220,9 +197,7 @@ public final class CallForwardingInfo implements Parcelable {
* Returns the phone number to which calls will be forwarded.
*
* @return the number calls will be forwarded to, or {@code null} if call forwarding
- * is being disabled.
- *
- * @hide
+ * is disabled.
*/
@Nullable
public String getNumber() {
@@ -230,16 +205,14 @@ public final class CallForwardingInfo implements Parcelable {
}
/**
- * Gets the timeout (in seconds) before the forwarding is attempted. For example,
+ * Gets the timeout (in seconds) before forwarding is attempted. For example,
* if {@link #REASON_NO_REPLY} is the call forwarding reason, the device will wait this
- * duration of time before forwarding the call to {@link #getNumber()}.
+ * duration of time before forwarding the call to the number returned by {@link #getNumber()}.
*
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10
* 7.11 Call forwarding number and conditions +CCFC
*
* @return the timeout (in seconds) before the forwarding is attempted.
- *
- * @hide
*/
@SuppressLint("MethodNameUnits")
public int getTimeoutSeconds() {
@@ -257,14 +230,14 @@ public final class CallForwardingInfo implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(mNumber);
- out.writeInt(mStatus);
+ out.writeBoolean(mEnabled);
out.writeInt(mReason);
out.writeInt(mTimeSeconds);
}
private CallForwardingInfo(Parcel in) {
mNumber = in.readString();
- mStatus = in.readInt();
+ mEnabled = in.readBoolean();
mReason = in.readInt();
mTimeSeconds = in.readInt();
}
@@ -281,7 +254,7 @@ public final class CallForwardingInfo implements Parcelable {
}
CallForwardingInfo other = (CallForwardingInfo) o;
- return mStatus == other.mStatus
+ return mEnabled == other.mEnabled
&& mNumber == other.mNumber
&& mReason == other.mReason
&& mTimeSeconds == other.mTimeSeconds;
@@ -292,7 +265,7 @@ public final class CallForwardingInfo implements Parcelable {
*/
@Override
public int hashCode() {
- return Objects.hash(mStatus, mNumber, mReason, mTimeSeconds);
+ return Objects.hash(mEnabled, mNumber, mReason, mTimeSeconds);
}
public static final @NonNull Parcelable.Creator<CallForwardingInfo> CREATOR =
@@ -313,7 +286,7 @@ public final class CallForwardingInfo implements Parcelable {
*/
@Override
public String toString() {
- return "[CallForwardingInfo: status=" + mStatus
+ return "[CallForwardingInfo: enabled=" + mEnabled
+ ", reason= " + mReason
+ ", timeSec= " + mTimeSeconds + " seconds"
+ ", number=" + Rlog.pii(TAG, mNumber) + "]";
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 829c746c1b5f..47bc566a331a 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -68,7 +68,7 @@ public class CarrierConfigManager {
SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
/**
- * Service class flag if not specify a service class.
+ * Service class flag if no specific service class is specified.
* Reference: 3GPP TS 27.007 Section 7.4 Facility lock +CLCK
*/
public static final int SERVICE_CLASS_NONE = ImsSsData.SERVICE_CLASS_NONE;
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 905f90800305..3923c756033f 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -138,7 +138,11 @@ public final class CellIdentityNr extends CellIdentity {
@NonNull
@Override
public CellLocation asCellLocation() {
- return new GsmCellLocation();
+ GsmCellLocation cl = new GsmCellLocation();
+ int tac = mTac != CellInfo.UNAVAILABLE ? mTac : -1;
+ cl.setLacAndCid(tac, -1);
+ cl.setPsc(0);
+ return cl;
}
@Override
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 559a7747788a..0ec27933dc36 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -99,6 +99,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IBooleanConsumer;
+import com.android.internal.telephony.ICallForwardingInfoCallback;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.IOns;
import com.android.internal.telephony.IPhoneSubInfo;
@@ -13020,195 +13022,304 @@ public class TelephonyManager {
}
/**
- * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
- * reason.
+ * Callback to be used with {@link #getCallForwarding}
+ * @hide
+ */
+ @SystemApi
+ public interface CallForwardingInfoCallback {
+ /**
+ * Called when the call forwarding info is successfully retrieved from the network.
+ * @param info information about how calls are forwarded
+ */
+ void onCallForwardingInfoAvailable(@NonNull CallForwardingInfo info);
+
+ /**
+ * Called when there was an error retrieving the call forwarding information.
+ * @param error
+ */
+ void onError(@CallForwardingInfo.CallForwardingError int error);
+ }
+
+ /**
+ * Gets the voice call forwarding info for a given call forwarding reason.
*
- * @param callForwardingReason the call forwarding reasons
+ * This method queries the network for the currently set call forwarding configuration for the
+ * provided call forwarding reason. When the network has provided its response, the result will
+ * be supplied via the provided {@link Executor} on the provided
+ * {@link CallForwardingInfoCallback}.
*
- * @throws IllegalArgumentException if callForwardingReason is not any of
- * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
- * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
- * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
+ * @param callForwardingReason the call forwarding reason to query.
+ * @param executor The executor on which to execute the callback once the result is ready.
+ * @param callback The callback the results should be delivered on.
*
- * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
- * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
- * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
- * {@link CallForwardingInfo#STATUS_UNKNOWN_ERROR},
- * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED},
- * or {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
+ * @throws IllegalArgumentException if callForwardingReason is not any of
+ * {@link CallForwardingInfo#REASON_UNCONDITIONAL}, {@link CallForwardingInfo#REASON_BUSY},
+ * {@link CallForwardingInfo#REASON_NO_REPLY}, {@link CallForwardingInfo#REASON_NOT_REACHABLE},
+ * {@link CallForwardingInfo#REASON_ALL}, or {@link CallForwardingInfo#REASON_ALL_CONDITIONAL}
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @NonNull
- public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) {
+ @SystemApi
+ public void getCallForwarding(@CallForwardingReason int callForwardingReason,
+ @NonNull Executor executor, @NonNull CallForwardingInfoCallback callback) {
if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
|| callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
throw new IllegalArgumentException("callForwardingReason is out of range");
}
+
+ ICallForwardingInfoCallback internalCallback = new ICallForwardingInfoCallback.Stub() {
+ @Override
+ public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
+ executor.execute(() ->
+ Binder.withCleanCallingIdentity(() ->
+ callback.onCallForwardingInfoAvailable(info)));
+ }
+
+ @Override
+ public void onError(int error) {
+ executor.execute(() ->
+ Binder.withCleanCallingIdentity(() ->
+ callback.onError(error)));
+ }
+ };
+
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCallForwarding(getSubId(), callForwardingReason);
+ telephony.getCallForwarding(getSubId(), callForwardingReason, internalCallback);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getCallForwarding RemoteException", ex);
- } catch (NullPointerException ex) {
- Rlog.e(TAG, "getCallForwarding NPE", ex);
+ ex.rethrowAsRuntimeException();
}
- return new CallForwardingInfo(
- CallForwardingInfo.STATUS_UNKNOWN_ERROR, 0 /* reason */, null /* number */,
- 0 /* timeout */);
}
/**
- * Sets the voice call forwarding info including status (enable/disable), call forwarding
- * reason, the number to forward, and the timeout before the forwarding is attempted.
+ * Sets voice call forwarding behavior as described by the provided {@link CallForwardingInfo}.
*
- * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
- * Enabling if {@link CallForwardingInfo#getStatus()} returns
- * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
- * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
+ * This method will enable call forwarding if the provided {@link CallForwardingInfo} returns
+ * {@code true} from its {@link CallForwardingInfo#isEnabled()} method, and disables call
+ * forwarding otherwise.
*
- * @throws IllegalArgumentException if any of the following for parameter callForwardingInfo:
- * 0) it is {@code null}.
- * 1) {@link CallForwardingInfo#getStatus()} returns neither
- * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
- * 2) {@link CallForwardingInfo#getReason()} is not any of
- * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
- * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
- * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
- * 3) {@link CallForwardingInfo#getNumber()} returns {@code null}.
- * 4) {@link CallForwardingInfo#getTimeoutSeconds()} doesn't return a positive value.
+ * If you wish to be notified about the results of this operation, provide an {@link Executor}
+ * and {@link Consumer<Integer>} to be notified asynchronously when the operation completes.
*
- * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ * @param callForwardingInfo Info about whether calls should be forwarded and where they
+ * should be forwarded to.
+ * @param executor The executor on which the listener will be called. Must be non-null if
+ * {@code listener} is non-null.
+ * @param resultListener Asynchronous listener that'll be called when the operation completes.
+ * Called with {@link CallForwardingInfo#SUCCESS} if the operation
+ * succeeded and an error code from {@link CallForwardingInfo}
+ * if it failed.
*
+ * @throws IllegalArgumentException if any of the following are true for the parameter
+ * callForwardingInfo:
+ * <ul>
+ * <li>it is {@code null}.</li>
+ * <li>{@link CallForwardingInfo#getReason()} is not any of:
+ * <ul>
+ * <li>{@link CallForwardingInfo#REASON_UNCONDITIONAL}</li>
+ * <li>{@link CallForwardingInfo#REASON_BUSY}</li>
+ * <li>{@link CallForwardingInfo#REASON_NO_REPLY}</li>
+ * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE}</li>
+ * <li>{@link CallForwardingInfo#REASON_ALL}</li>
+ * <li>{@link CallForwardingInfo#REASON_ALL_CONDITIONAL}</li>
+ * </ul>
+ * <li>{@link CallForwardingInfo#getNumber()} returns {@code null} when enabling call
+ * forwarding</li>
+ * <li>{@link CallForwardingInfo#getTimeoutSeconds()} returns a non-positive value when
+ * enabling call forwarding</li>
+ * </ul>
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) {
+ @SystemApi
+ public void setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo,
+ @Nullable @CallbackExecutor Executor executor,
+ @Nullable @CallForwardingInfo.CallForwardingError Consumer<Integer> resultListener) {
if (callForwardingInfo == null) {
throw new IllegalArgumentException("callForwardingInfo is null");
}
- int callForwardingStatus = callForwardingInfo.getStatus();
- if (callForwardingStatus != CallForwardingInfo.STATUS_ACTIVE
- && callForwardingStatus != CallForwardingInfo.STATUS_INACTIVE) {
- throw new IllegalArgumentException(
- "callForwardingStatus is neither active nor inactive");
- }
int callForwardingReason = callForwardingInfo.getReason();
if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
|| callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
throw new IllegalArgumentException("callForwardingReason is out of range");
}
- if (callForwardingInfo.getNumber() == null) {
- throw new IllegalArgumentException("callForwarding number is null");
+ if (callForwardingInfo.isEnabled()) {
+ if (callForwardingInfo.getNumber() == null) {
+ throw new IllegalArgumentException("callForwarding number is null");
+ }
+ if (callForwardingInfo.getTimeoutSeconds() <= 0) {
+ throw new IllegalArgumentException("callForwarding timeout isn't positive");
+ }
}
- if (callForwardingInfo.getTimeoutSeconds() <= 0) {
- throw new IllegalArgumentException("callForwarding timeout isn't positive");
+ if (resultListener != null) {
+ Objects.requireNonNull(executor);
}
+
+ IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() ->
+ Binder.withCleanCallingIdentity(() -> resultListener.accept(result)));
+ }
+ };
+
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.setCallForwarding(getSubId(), callForwardingInfo);
+ telephony.setCallForwarding(getSubId(), callForwardingInfo, internalCallback);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "setCallForwarding RemoteException", ex);
+ ex.rethrowAsRuntimeException();
} catch (NullPointerException ex) {
Rlog.e(TAG, "setCallForwarding NPE", ex);
+ throw ex;
}
- return false;
}
/**
- * Indicates the call waiting status is active.
+ * Indicates that call waiting is enabled.
*
* @hide
*/
- public static final int CALL_WAITING_STATUS_ACTIVE = 1;
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_ENABLED = 1;
/**
- * Indicates the call waiting status is inactive.
+ * Indicates that call waiting is disabled.
*
* @hide
*/
- public static final int CALL_WAITING_STATUS_INACTIVE = 2;
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_DISABLED = 2;
/**
- * Indicates the call waiting status is with an unknown error.
+ * Indicates there was an unknown error retrieving the call waiting status.
*
* @hide
*/
+ @SystemApi
public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3;
/**
- * Indicates the call waiting is not supported (e.g. called via CDMA).
+ * Indicates the call waiting is not supported on the current network.
*
* @hide
*/
+ @SystemApi
public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4;
/**
- * Call waiting function status
- *
* @hide
*/
@IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = {
- CALL_WAITING_STATUS_ACTIVE,
- CALL_WAITING_STATUS_INACTIVE,
- CALL_WAITING_STATUS_NOT_SUPPORTED,
- CALL_WAITING_STATUS_UNKNOWN_ERROR
+ CALL_WAITING_STATUS_ENABLED,
+ CALL_WAITING_STATUS_DISABLED,
+ CALL_WAITING_STATUS_UNKNOWN_ERROR,
+ CALL_WAITING_STATUS_NOT_SUPPORTED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CallWaitingStatus {
}
/**
- * Gets the status of voice call waiting function. Call waiting function enables the waiting
- * for the incoming call when it reaches the user who is busy to make another call and allows
- * users to decide whether to switch to the incoming call.
+ * Retrieves the call waiting status of this device from the network.
+ *
+ * When call waiting is enabled, an incoming call that arrives when the user is already on
+ * an active call will be held in a waiting state while the user is notified instead of being
+ * rejected with a busy signal.
*
- * @return the status of call waiting function.
+ * @param executor The executor on which the result listener will be called.
+ * @param resultListener A {@link Consumer} that will be called with the result fetched
+ * from the network. The result will be one of:
+ * <ul>
+ * <li>{@link #CALL_WAITING_STATUS_ENABLED}}</li>
+ * <li>{@link #CALL_WAITING_STATUS_DISABLED}}</li>
+ * <li>{@link #CALL_WAITING_STATUS_UNKNOWN_ERROR}}</li>
+ * <li>{@link #CALL_WAITING_STATUS_NOT_SUPPORTED}}</li>
+ * </ul>
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public @CallWaitingStatus int getCallWaitingStatus() {
+ public void getCallWaitingStatus(@NonNull Executor executor,
+ @NonNull @CallWaitingStatus Consumer<Integer> resultListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(resultListener);
+
+ IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCallWaitingStatus(getSubId());
+ telephony.getCallWaitingStatus(getSubId(), internalCallback);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getCallWaitingStatus RemoteException", ex);
+ ex.rethrowAsRuntimeException();
} catch (NullPointerException ex) {
Rlog.e(TAG, "getCallWaitingStatus NPE", ex);
+ throw ex;
}
- return CALL_WAITING_STATUS_UNKNOWN_ERROR;
}
/**
- * Sets the status for voice call waiting function. Call waiting function enables the waiting
- * for the incoming call when it reaches the user who is busy to make another call and allows
- * users to decide whether to switch to the incoming call.
+ * Sets the call waiting status of this device with the network.
+ *
+ * If you wish to be notified about the results of this operation, provide an {@link Executor}
+ * and {@link Consumer<Integer>} to be notified asynchronously when the operation completes.
*
- * @param isEnable {@code true} to enable; {@code false} to disable.
- * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ * @see #getCallWaitingStatus for a description of the call waiting functionality.
*
+ * @param enabled {@code true} to enable; {@code false} to disable.
+ * @param executor The executor on which the listener will be called. Must be non-null if
+ * {@code listener} is non-null.
+ * @param resultListener Asynchronous listener that'll be called when the operation completes.
+ * Called with the new call waiting status (either
+ * {@link #CALL_WAITING_STATUS_ENABLED} or
+ * {@link #CALL_WAITING_STATUS_DISABLED} if the operation succeeded and
+ * {@link #CALL_WAITING_STATUS_NOT_SUPPORTED} or
+ * {@link #CALL_WAITING_STATUS_UNKNOWN_ERROR} if it failed.
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public boolean setCallWaitingStatus(boolean isEnable) {
+ public void setCallWaitingStatus(boolean enabled, @Nullable Executor executor,
+ @Nullable Consumer<Integer> resultListener) {
+ if (resultListener != null) {
+ Objects.requireNonNull(executor);
+ }
+
+ IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() ->
+ Binder.withCleanCallingIdentity(() -> resultListener.accept(result)));
+ }
+ };
+
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.setCallWaitingStatus(getSubId(), isEnable);
+ telephony.setCallWaitingStatus(getSubId(), enabled, internalCallback);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "setCallWaitingStatus RemoteException", ex);
+ ex.rethrowAsRuntimeException();
} catch (NullPointerException ex) {
Rlog.e(TAG, "setCallWaitingStatus NPE", ex);
+ throw ex;
}
- return false;
}
/**
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index 30cea0e6dd59..bc8ee1dd9359 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -55,7 +55,7 @@ public class GsmCellLocation extends CellLocation {
}
/**
- * @return gsm cell id, -1 if unknown, 0xffff max legal value
+ * @return gsm cell id, -1 if unknown or invalid, 0xffff max legal value
*/
public int getCid() {
return mCid;
diff --git a/telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl b/telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl
new file mode 100644
index 000000000000..4d3b9f4636df
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ICallForwardingInfoCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.telephony;
+
+import android.telephony.CallForwardingInfo;
+
+// Callback interface for the getCallForwarding API in TelephonyManager.
+oneway interface ICallForwardingInfoCallback {
+ void onCallForwardingInfoAvailable(in CallForwardingInfo info);
+ void onError(int error);
+} \ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4021d0a2888f..02a74ba53ccb 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -58,6 +58,7 @@ import android.telephony.ims.aidl.IImsRegistrationCallback;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IBooleanConsumer;
+import com.android.internal.telephony.ICallForwardingInfoCallback;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.OperatorInfo;
@@ -1648,78 +1649,15 @@ interface ITelephony {
*/
void carrierActionResetAll(int subId);
- /**
- * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
- * reason.
- *
- * @param callForwardingReason the call forwarding reasons which are the bitwise-OR combination
- * of the following constants:
- * <ol>
- * <li>{@link CallForwardingInfo#REASON_BUSY} </li>
- * <li>{@link CallForwardingInfo#REASON_NO_REPLY} </li>
- * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE} </li>
- * </ol>
- *
- * @throws IllegalArgumentException if callForwardingReason is not a bitwise-OR combination
- * of {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_BUSY},
- * {@link CallForwardingInfo.REASON_NOT_REACHABLE}
- *
- * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
- * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
- * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
- * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED} or
- * {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
- *
- * @hide
- */
- CallForwardingInfo getCallForwarding(int subId, int callForwardingReason);
+ void getCallForwarding(int subId, int callForwardingReason,
+ ICallForwardingInfoCallback callback);
- /**
- * Sets the voice call forwarding info including status (enable/disable), call forwarding
- * reason, the number to forward, and the timeout before the forwarding is attempted.
- *
- * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
- * Enabling if {@link CallForwardingInfo#getStatus()} returns
- * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
- * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
- *
- * @throws IllegalArgumentException if any of the following:
- * 0) callForwardingInfo is null.
- * 1) {@link CallForwardingInfo#getStatus()} for callForwardingInfo returns neither
- * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
- * 2) {@link CallForwardingInfo#getReason()} for callForwardingInfo doesn't return the
- * bitwise-OR combination of {@link CallForwardingInfo.REASON_BUSY},
- * {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE}
- * 3) {@link CallForwardingInfo#getNumber()} for callForwardingInfo returns null.
- * 4) {@link CallForwardingInfo#getTimeout()} for callForwardingInfo returns nagetive value.
- *
- * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
- *
- * @hide
- */
- boolean setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo);
+ void setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo,
+ IIntegerConsumer callback);
- /**
- * Gets the status of voice call waiting function. Call waiting function enables the waiting
- * for the incoming call when it reaches the user who is busy to make another call and allows
- * users to decide whether to switch to the incoming call.
- *
- * @return the status of call waiting function.
- * @hide
- */
- int getCallWaitingStatus(int subId);
+ void getCallWaitingStatus(int subId, IIntegerConsumer callback);
- /**
- * Sets the status for voice call waiting function. Call waiting function enables the waiting
- * for the incoming call when it reaches the user who is busy to make another call and allows
- * users to decide whether to switch to the incoming call.
- *
- * @param isEnable {@code true} to enable; {@code false} to disable.
- * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
- *
- * @hide
- */
- boolean setCallWaitingStatus(int subId, boolean isEnable);
+ void setCallWaitingStatus(int subId, boolean enabled, IIntegerConsumer callback);
/**
* Get Client request stats which will contain statistical information
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index 9324ba0b8b72..380e29984c63 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -23,7 +23,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
@@ -31,6 +30,7 @@ import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.soundtrigger.SoundTriggerDetector;
+import android.media.soundtrigger.SoundTriggerManager;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -232,8 +232,8 @@ public class SoundTriggerTestService extends Service {
public AudioTrack captureAudioTrack;
}
- private GenericSoundModel createNewSoundModel(ModelInfo modelInfo) {
- return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid,
+ private SoundTriggerManager.Model createNewSoundModel(ModelInfo modelInfo) {
+ return SoundTriggerManager.Model.create(modelInfo.modelUuid, modelInfo.vendorUuid,
modelInfo.modelData);
}
@@ -246,16 +246,16 @@ public class SoundTriggerTestService extends Service {
postMessage("Loading model: " + modelInfo.name);
- GenericSoundModel soundModel = createNewSoundModel(modelInfo);
+ SoundTriggerManager.Model soundModel = createNewSoundModel(modelInfo);
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(soundModel);
if (status) {
postToast("Successfully loaded " + modelInfo.name + ", UUID="
- + soundModel.getUuid());
+ + soundModel.getModelUuid());
setModelState(modelInfo, "Loaded");
} else {
postErrorToast("Failed to load " + modelInfo.name + ", UUID="
- + soundModel.getUuid() + "!");
+ + soundModel.getModelUuid() + "!");
setModelState(modelInfo, "Failed to load");
}
}
@@ -269,7 +269,7 @@ public class SoundTriggerTestService extends Service {
postMessage("Unloading model: " + modelInfo.name);
- GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
+ SoundTriggerManager.Model soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
if (soundModel == null) {
postErrorToast("Sound model not found for " + modelInfo.name + "!");
return;
@@ -278,11 +278,11 @@ public class SoundTriggerTestService extends Service {
boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
if (status) {
postToast("Successfully unloaded " + modelInfo.name + ", UUID="
- + soundModel.getUuid());
+ + soundModel.getModelUuid());
setModelState(modelInfo, "Unloaded");
} else {
postErrorToast("Failed to unload " +
- modelInfo.name + ", UUID=" + soundModel.getUuid() + "!");
+ modelInfo.name + ", UUID=" + soundModel.getModelUuid() + "!");
setModelState(modelInfo, "Failed to unload");
}
}
@@ -294,12 +294,12 @@ public class SoundTriggerTestService extends Service {
return;
}
postMessage("Reloading model: " + modelInfo.name);
- GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
+ SoundTriggerManager.Model soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
if (soundModel == null) {
postErrorToast("Sound model not found for " + modelInfo.name + "!");
return;
}
- GenericSoundModel updated = createNewSoundModel(modelInfo);
+ SoundTriggerManager.Model updated = createNewSoundModel(modelInfo);
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
if (status) {
postToast("Successfully reloaded " + modelInfo.name + ", UUID="
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
index 6b89b62bb1e3..cfe8c855ac81 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
@@ -18,7 +18,6 @@ package com.android.test.soundtrigger;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.media.soundtrigger.SoundTriggerDetector;
import android.media.soundtrigger.SoundTriggerManager;
import android.os.RemoteException;
@@ -37,13 +36,10 @@ import java.util.UUID;
public class SoundTriggerUtil {
private static final String TAG = "SoundTriggerTestUtil";
- private final ISoundTriggerService mSoundTriggerService;
private final SoundTriggerManager mSoundTriggerManager;
private final Context mContext;
public SoundTriggerUtil(Context context) {
- mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
- ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
Context.SOUND_TRIGGER_SERVICE);
mContext = context;
@@ -55,15 +51,11 @@ public class SoundTriggerUtil {
*
* @param soundModel The sound model to add/update.
*/
- public boolean addOrUpdateSoundModel(GenericSoundModel soundModel) {
- try {
- if (soundModel == null) {
- throw new RuntimeException("Bad sound model");
- }
- mSoundTriggerService.updateSoundModel(soundModel);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in updateSoundModel", e);
+ public boolean addOrUpdateSoundModel(SoundTriggerManager.Model soundModel) {
+ if (soundModel == null) {
+ throw new RuntimeException("Bad sound model");
}
+ mSoundTriggerManager.updateModel(soundModel);
return true;
}
@@ -71,19 +63,15 @@ public class SoundTriggerUtil {
* Gets the sound model for the given keyphrase, null if none exists.
* If a sound model for a given keyphrase exists, and it needs to be updated,
* it should be obtained using this method, updated and then passed in to
- * {@link #addOrUpdateSoundModel(GenericSoundModel)} without changing the IDs.
+ * {@link #addOrUpdateSoundModel(SoundTriggerManager.Model)} without changing the IDs.
*
* @param modelId The model ID to look-up the sound model for.
* @return The sound model if one was found, null otherwise.
*/
@Nullable
- public GenericSoundModel getSoundModel(UUID modelId) {
- GenericSoundModel model = null;
- try {
- model = mSoundTriggerService.getSoundModel(new ParcelUuid(modelId));
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in updateKeyphraseSoundModel");
- }
+ public SoundTriggerManager.Model getSoundModel(UUID modelId) {
+ SoundTriggerManager.Model model = null;
+ model = mSoundTriggerManager.getModel(modelId);
if (model == null) {
Log.w(TAG, "No models present for the given keyphrase ID");
@@ -100,12 +88,7 @@ public class SoundTriggerUtil {
* @return {@code true} if the call succeeds, {@code false} otherwise.
*/
public boolean deleteSoundModel(UUID modelId) {
- try {
- mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelId));
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in deleteSoundModel");
- return false;
- }
+ mSoundTriggerManager.deleteModel(modelId);
return true;
}
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index ed5ed82e6adf..aab4a2df7633 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -332,6 +332,7 @@ package android.net.wifi {
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001; // 0x3e9
field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
field @Deprecated public boolean allowAutojoin;
field @Deprecated public int carrierId;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 54ec1e1c7c0b..329ca37407de 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -587,12 +587,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;
/**
* 60 GHz band first channel number
@@ -645,7 +651,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);
}
/**
@@ -687,6 +696,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;
@@ -711,6 +723,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/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 02b7a42d3878..391be357e963 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1206,12 +1206,18 @@ public class WifiConfiguration implements Parcelable {
/**
* @hide
- * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in aggressive
- * randomization mode.
+ * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in enhanced
+ * MAC randomization mode.
*/
public long randomizedMacExpirationTimeMs = 0;
/**
+ * The wall clock time of when |mRandomizedMacAddress| is last modified.
+ * @hide
+ */
+ public long randomizedMacLastModifiedTimeMs = 0;
+
+ /**
* @hide
* Checks if the given MAC address can be used for Connected Mac Randomization
* by verifying that it is non-null, unicast, locally assigned, and not default mac.
@@ -2060,7 +2066,8 @@ public class WifiConfiguration implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "RECENT_FAILURE_", value = {
RECENT_FAILURE_NONE,
- RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA})
+ RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA,
+ RECENT_FAILURE_MBO_OCE_DISCONNECT})
public @interface RecentFailureReason {}
/**
@@ -2078,6 +2085,13 @@ public class WifiConfiguration implements Parcelable {
public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
/**
+ * This network recently disconnected as a result of MBO/OCE.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001;
+
+ /**
* Get the failure reason for the most recent connection attempt, or
* {@link #RECENT_FAILURE_NONE} if there was no failure.
*
@@ -2281,6 +2295,9 @@ public class WifiConfiguration implements Parcelable {
sbuf.append(" randomizedMacExpirationTimeMs: ")
.append(randomizedMacExpirationTimeMs == 0 ? "<none>"
: logTimeOfDay(randomizedMacExpirationTimeMs)).append("\n");
+ sbuf.append(" randomizedMacLastModifiedTimeMs: ")
+ .append(randomizedMacLastModifiedTimeMs == 0 ? "<none>"
+ : logTimeOfDay(randomizedMacLastModifiedTimeMs)).append("\n");
sbuf.append(" KeyMgmt:");
for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
if (this.allowedKeyManagement.get(k)) {
@@ -2837,6 +2854,7 @@ public class WifiConfiguration implements Parcelable {
mRandomizedMacAddress = source.mRandomizedMacAddress;
macRandomizationSetting = source.macRandomizationSetting;
randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs;
+ randomizedMacLastModifiedTimeMs = source.randomizedMacLastModifiedTimeMs;
requirePmf = source.requirePmf;
updateIdentifier = source.updateIdentifier;
carrierId = source.carrierId;
@@ -2911,6 +2929,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(macRandomizationSetting);
dest.writeInt(osu ? 1 : 0);
dest.writeLong(randomizedMacExpirationTimeMs);
+ dest.writeLong(randomizedMacLastModifiedTimeMs);
dest.writeInt(carrierId);
dest.writeString(mPasspointUniqueId);
}
@@ -2985,6 +3004,7 @@ public class WifiConfiguration implements Parcelable {
config.macRandomizationSetting = in.readInt();
config.osu = in.readInt() != 0;
config.randomizedMacExpirationTimeMs = in.readLong();
+ config.randomizedMacLastModifiedTimeMs = in.readLong();
config.carrierId = in.readInt();
config.mPasspointUniqueId = in.readString();
return config;
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 4a3586826de9..59b88a7f0c3f 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -103,9 +103,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
};
/**