summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java71
-rw-r--r--apex/media/framework/Android.bp26
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java159
-rw-r--r--apex/media/framework/jni/android_media_MediaParserJNI.cpp92
-rw-r--r--cmds/incidentd/src/IncidentService.cpp4
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java14
-rw-r--r--core/java/android/accounts/GrantCredentialsPermissionActivity.java37
-rw-r--r--core/java/android/app/ActivityOptions.java8
-rw-r--r--core/java/android/app/ActivityView.java15
-rw-r--r--core/java/android/app/AppOpsManager.java47
-rw-r--r--core/java/android/app/LoadedApk.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java6
-rw-r--r--core/java/android/app/slice/SliceProvider.java1
-rw-r--r--core/java/android/bluetooth/BluetoothCodecStatus.java9
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java2
-rw-r--r--core/java/android/companion/AssociationRequest.java29
-rw-r--r--core/java/android/content/pm/CrossProfileApps.java10
-rw-r--r--core/java/android/content/pm/PackageManager.java16
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java4
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java12
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java5
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java5
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java30
-rw-r--r--core/java/android/hardware/display/DisplayManager.java55
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java47
-rw-r--r--core/java/android/os/IPowerManager.aidl2
-rw-r--r--core/java/android/os/PowerManager.java21
-rw-r--r--core/java/android/provider/DocumentsProvider.java42
-rwxr-xr-xcore/java/android/provider/Settings.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java2
-rw-r--r--core/java/android/widget/TextView.java8
-rw-r--r--core/java/android/window/VirtualDisplayTaskEmbedder.java9
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java2
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java16
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java2
-rw-r--r--core/jni/android_hardware_camera2_CameraMetadata.cpp13
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/res/values-am/strings.xml4
-rw-r--r--core/res/res/values-az/strings.xml16
-rw-r--r--core/res/res/values-be/strings.xml40
-rw-r--r--core/res/res/values-bs/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml6
-rw-r--r--core/res/res/values-en-rCA/strings.xml6
-rw-r--r--core/res/res/values-es/strings.xml2
-rw-r--r--core/res/res/values-fi/strings.xml4
-rw-r--r--core/res/res/values-fr/strings.xml2
-rw-r--r--core/res/res/values-gl/strings.xml2
-rw-r--r--core/res/res/values-gu/strings.xml6
-rw-r--r--core/res/res/values-hu/strings.xml6
-rw-r--r--core/res/res/values-hy/strings.xml20
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-km/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml4
-rw-r--r--core/res/res/values-nb/strings.xml2
-rw-r--r--core/res/res/values-pa/strings.xml2
-rw-r--r--core/res/res/values-ru/strings.xml2
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-uk/strings.xml4
-rw-r--r--core/res/res/values/config.xml29
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java19
-rw-r--r--data/etc/car/Android.bp7
-rw-r--r--data/etc/car/com.android.car.shell.xml22
-rw-r--r--data/etc/car/com.google.android.car.kitchensink.xml3
-rw-r--r--data/etc/com.android.settings.xml2
-rw-r--r--diff25
-rw-r--r--drm/jni/Android.bp1
-rw-r--r--graphics/java/android/graphics/Typeface.java6
-rw-r--r--packages/CarSystemUI/res/layout/headsup_container_bottom.xml7
-rw-r--r--packages/CarSystemUI/res/values-af/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-am/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ar/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-as/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-az/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-b+sr+Latn/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-be/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-bg/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-bn/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-bs/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ca/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-cs/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-da/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-de/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-el/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-en-rAU/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-en-rCA/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-en-rGB/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-en-rIN/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-en-rXC/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-es-rUS/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-es/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-et/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-eu/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-fa/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-fi/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-fr-rCA/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-fr/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-gl/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-gu/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-hi/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-hr/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-hu/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-hy/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-in/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-is/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-it/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-iw/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ja/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ka/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-kk/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-km/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-kn/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ko/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ky/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-lo/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-lt/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-lv/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-mk/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ml/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-mn/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-mr/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ms/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-my/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-nb/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ne/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-nl/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-or/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-pa/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-pl/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-pt-rPT/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-pt/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ro/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ru/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-si/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sk/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sl/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sq/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sr/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sv/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-sw/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ta/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-te/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-th/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-tl/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-tr/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-uk/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-ur/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-uz/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-vi/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-zh-rCN/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-zh-rHK/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-zh-rTW/strings.xml31
-rw-r--r--packages/CarSystemUI/res/values-zu/strings.xml31
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java7
-rw-r--r--packages/PackageInstaller/res/values-es/strings.xml4
-rw-r--r--packages/PackageInstaller/res/values-nl/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-or/strings.xml2
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java3
-rwxr-xr-xpackages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java3
-rw-r--r--packages/PrintSpooler/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-ar/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-ar/strings.xml2
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml2
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-es/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-fa/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-ja/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-mr/strings.xml2
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-or/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-te/strings.xml4
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/res/values-vi/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-be/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-el/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-fa/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-hi/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-hr/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-hy/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-in/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-is/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-pa/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-sq/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-tl/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-uk/strings.xml2
-rw-r--r--packages/SettingsLib/SearchWidget/res/values-vi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bn/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-bs/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml2
-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/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-in/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-it/arrays.xml20
-rw-r--r--packages/SettingsLib/res/values-ja/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-ne/arrays.xml2
-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-th/strings.xml2
-rw-r--r--packages/SettingsLib/res/values/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java33
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt3
-rw-r--r--packages/SettingsProvider/res/values-fa/strings.xml2
-rw-r--r--packages/Shell/res/values-it/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-az/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-es/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-gl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-in/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-it/strings.xml4
-rw-r--r--packages/SystemUI/res-keyguard/values-kk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-km/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ko/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ky/strings.xml6
-rw-r--r--packages/SystemUI/res-keyguard/values-ne/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pt/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sq/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-th/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ur/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-uz/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-vi/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml3
-rw-r--r--packages/SystemUI/res/layout/controls_dialog_pin.xml1
-rw-r--r--packages/SystemUI/res/values-fi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BackGestureTfClassifierProvider.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java132
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ToggleRangeTemplateTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java30
-rw-r--r--packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml219
-rw-r--r--packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml204
-rw-r--r--packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml18
-rw-r--r--packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_work_apps_off.xml19
-rw-r--r--packages/overlays/IconShapePebbleOverlay/res/values/config.xml2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java13
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java74
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java39
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java248
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java4
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java11
-rw-r--r--services/core/Android.bp7
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java55
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java45
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java123
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java7
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java51
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java17
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java6
-rw-r--r--services/core/java/com/android/server/biometrics/AuthenticationClient.java53
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java1
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java15
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java667
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java3
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java21
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java7
-rw-r--r--services/core/java/com/android/server/notification/InjectableSystemClock.java44
-rw-r--r--services/core/java/com/android/server/notification/InjectableSystemClockImpl.java51
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java315
-rw-r--r--services/core/java/com/android/server/notification/NotificationUsageStats.java386
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java54
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java37
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java151
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtManagerService.java8
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java19
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java90
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java16
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java16
-rw-r--r--services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java71
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java16
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java36
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java58
-rw-r--r--services/core/java/com/android/server/utils/DeviceConfigInterface.java (renamed from services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java)13
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java72
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java20
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java27
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java35
-rw-r--r--services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java2
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java34
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java9
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java15
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerConstants.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java20
-rw-r--r--services/tests/servicestests/Android.bp3
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java417
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java70
-rw-r--r--services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java23
-rw-r--r--services/tests/servicestests/utils/com/android/server/testutils/FakeDeviceConfigInterface.java (renamed from services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java)16
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java3
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java111
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java145
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java48
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java43
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java2
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java8
-rw-r--r--tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java13
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java52
-rw-r--r--tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java8
-rw-r--r--tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java76
371 files changed, 5307 insertions, 4055 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index bb94275fc409..ba8348337981 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -22,6 +22,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
+import android.annotation.Nullable;
import android.app.job.JobInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -86,9 +87,12 @@ public final class ConnectivityController extends RestrictingController implemen
@GuardedBy("mLock")
private final SparseArray<ArraySet<JobStatus>> mRequestedWhitelistJobs = new SparseArray<>();
- /** List of currently available networks. */
+ /**
+ * Set of currently available networks mapped to their latest network capabilities. Cache the
+ * latest capabilities to avoid unnecessary calls into ConnectivityManager.
+ */
@GuardedBy("mLock")
- private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
+ private final ArrayMap<Network, NetworkCapabilities> mAvailableNetworks = new ArrayMap<>();
private static final int MSG_DATA_SAVER_TOGGLED = 0;
private static final int MSG_UID_RULES_CHANGES = 1;
@@ -165,9 +169,8 @@ public final class ConnectivityController extends RestrictingController implemen
public boolean isNetworkAvailable(JobStatus job) {
synchronized (mLock) {
for (int i = 0; i < mAvailableNetworks.size(); ++i) {
- final Network network = mAvailableNetworks.valueAt(i);
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(
- network);
+ final Network network = mAvailableNetworks.keyAt(i);
+ final NetworkCapabilities capabilities = mAvailableNetworks.valueAt(i);
final boolean satisfied = isSatisfied(job, network, capabilities, mConstants);
if (DEBUG) {
Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network
@@ -427,9 +430,33 @@ public final class ConnectivityController extends RestrictingController implemen
return false;
}
+ @Nullable
+ private NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
+ if (network == null) {
+ return null;
+ }
+ synchronized (mLock) {
+ // There is technically a race here if the Network object is reused. This can happen
+ // only if that Network disconnects and the auto-incrementing network ID in
+ // ConnectivityService wraps. This should no longer be a concern if/when we only make
+ // use of asynchronous calls.
+ if (mAvailableNetworks.get(network) != null) {
+ return mAvailableNetworks.get(network);
+ }
+
+ // This should almost never happen because any time a new network connects, the
+ // NetworkCallback would populate mAvailableNetworks. However, it's currently necessary
+ // because we also call synchronous methods such as getActiveNetworkForUid.
+ // TODO(134978280): remove after switching to callback-based APIs
+ final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ mAvailableNetworks.put(network, capabilities);
+ return capabilities;
+ }
+ }
+
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ final NetworkCapabilities capabilities = getNetworkCapabilities(network);
return updateConstraintsSatisfied(jobStatus, network, capabilities);
}
@@ -470,19 +497,13 @@ public final class ConnectivityController extends RestrictingController implemen
*/
private void updateTrackedJobs(int filterUid, Network filterNetwork) {
synchronized (mLock) {
- // Since this is a really hot codepath, temporarily cache any
- // answers that we get from ConnectivityManager.
- final ArrayMap<Network, NetworkCapabilities> networkToCapabilities = new ArrayMap<>();
-
boolean changed = false;
if (filterUid == -1) {
for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
- changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i),
- filterNetwork, networkToCapabilities);
+ changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork);
}
} else {
- changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid),
- filterNetwork, networkToCapabilities);
+ changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork);
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
@@ -490,18 +511,13 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
- private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
- ArrayMap<Network, NetworkCapabilities> networkToCapabilities) {
+ private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork) {
if (jobs == null || jobs.size() == 0) {
return false;
}
final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
- NetworkCapabilities capabilities = networkToCapabilities.get(network);
- if (capabilities == null) {
- capabilities = mConnManager.getNetworkCapabilities(network);
- networkToCapabilities.put(network, capabilities);
- }
+ final NetworkCapabilities capabilities = getNetworkCapabilities(network);
final boolean networkMatch = (filterNetwork == null
|| Objects.equals(filterNetwork, network));
@@ -544,9 +560,9 @@ public final class ConnectivityController extends RestrictingController implemen
@Override
public void onAvailable(Network network) {
if (DEBUG) Slog.v(TAG, "onAvailable: " + network);
- synchronized (mLock) {
- mAvailableNetworks.add(network);
- }
+ // Documentation says not to call getNetworkCapabilities here but wait for
+ // onCapabilitiesChanged instead. onCapabilitiesChanged should be called immediately
+ // after this, so no need to update mAvailableNetworks here.
}
@Override
@@ -554,6 +570,9 @@ public final class ConnectivityController extends RestrictingController implemen
if (DEBUG) {
Slog.v(TAG, "onCapabilitiesChanged: " + network);
}
+ synchronized (mLock) {
+ mAvailableNetworks.put(network, capabilities);
+ }
updateTrackedJobs(-1, network);
}
@@ -630,6 +649,8 @@ public final class ConnectivityController extends RestrictingController implemen
pw.println("Available networks:");
pw.increaseIndent();
for (int i = 0; i < mAvailableNetworks.size(); i++) {
+ pw.print(mAvailableNetworks.keyAt(i));
+ pw.print(": ");
pw.println(mAvailableNetworks.valueAt(i));
}
pw.decreaseIndent();
@@ -667,7 +688,7 @@ public final class ConnectivityController extends RestrictingController implemen
mRequestedWhitelistJobs.keyAt(i));
}
for (int i = 0; i < mAvailableNetworks.size(); i++) {
- Network network = mAvailableNetworks.valueAt(i);
+ Network network = mAvailableNetworks.keyAt(i);
if (network != null) {
network.dumpDebug(proto,
StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS);
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index ce4b030467a7..3272fdf40062 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -35,7 +35,6 @@ java_library {
libs: [
"framework_media_annotation",
],
-
static_libs: [
"exoplayer2-extractor"
],
@@ -101,10 +100,33 @@ java_sdk_library {
impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
}
-
java_library {
name: "framework_media_annotation",
srcs: [":framework-media-annotation-srcs"],
installable: false,
sdk_version: "core_current",
}
+
+cc_library_shared {
+ name: "libmediaparser-jni",
+ srcs: [
+ "jni/android_media_MediaParserJNI.cpp",
+ ],
+ header_libs: ["jni_headers"],
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ "libmediametrics",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wunreachable-code",
+ "-Wunused",
+ ],
+ apex_available: [
+ "com.android.media",
+ ],
+ min_sdk_version: "29",
+}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index e4b5d19e67c9..8bdca766e0dd 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -75,6 +75,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.Function;
/**
* Parses media container formats and extracts contained media samples and metadata.
@@ -882,6 +884,7 @@ public final class MediaParser {
// Private constants.
private static final String TAG = "MediaParser";
+ private static final String JNI_LIBRARY_NAME = "mediaparser-jni";
private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
private static final String TS_MODE_SINGLE_PMT = "single_pmt";
@@ -889,6 +892,14 @@ public final class MediaParser {
private static final String TS_MODE_HLS = "hls";
private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ private static final String MEDIAMETRICS_ELEMENT_SEPARATOR = "|";
+ private static final int MEDIAMETRICS_MAX_STRING_SIZE = 200;
+ private static final int MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH;
+ /**
+ * Intentional error introduced to reported metrics to prevent identification of the parsed
+ * media. Note: Increasing this value may cause older hostside CTS tests to fail.
+ */
+ private static final float MEDIAMETRICS_DITHER = .02f;
@IntDef(
value = {
@@ -920,7 +931,7 @@ public final class MediaParser {
@NonNull @ParserName String name, @NonNull OutputConsumer outputConsumer) {
String[] nameAsArray = new String[] {name};
assertValidNames(nameAsArray);
- return new MediaParser(outputConsumer, /* sniff= */ false, name);
+ return new MediaParser(outputConsumer, /* createdByName= */ true, name);
}
/**
@@ -940,7 +951,7 @@ public final class MediaParser {
if (parserNames.length == 0) {
parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
}
- return new MediaParser(outputConsumer, /* sniff= */ true, parserNames);
+ return new MediaParser(outputConsumer, /* createdByName= */ false, parserNames);
}
// Misc static methods.
@@ -1052,6 +1063,14 @@ public final class MediaParser {
private long mPendingSeekPosition;
private long mPendingSeekTimeMicros;
private boolean mLoggedSchemeInitDataCreationException;
+ private boolean mReleased;
+
+ // MediaMetrics fields.
+ private final boolean mCreatedByName;
+ private final SparseArray<Format> mTrackFormats;
+ private String mLastObservedExceptionName;
+ private long mDurationMillis;
+ private long mResourceByteCount;
// Public methods.
@@ -1166,11 +1185,15 @@ public final class MediaParser {
if (mExtractorInput == null) {
// TODO: For efficiency, the same implementation should be used, by providing a
// clearBuffers() method, or similar.
+ long resourceLength = seekableInputReader.getLength();
+ if (mResourceByteCount == 0) {
+ // For resource byte count metric collection, we only take into account the length
+ // of the first provided input reader.
+ mResourceByteCount = resourceLength;
+ }
mExtractorInput =
new DefaultExtractorInput(
- mExoDataReader,
- seekableInputReader.getPosition(),
- seekableInputReader.getLength());
+ mExoDataReader, seekableInputReader.getPosition(), resourceLength);
}
mExoDataReader.mInputReader = seekableInputReader;
@@ -1195,7 +1218,10 @@ public final class MediaParser {
}
}
if (mExtractor == null) {
- throw UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
+ UnrecognizedInputFormatException exception =
+ UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
+ mLastObservedExceptionName = exception.getClass().getName();
+ throw exception;
}
return true;
}
@@ -1223,8 +1249,13 @@ public final class MediaParser {
int result;
try {
result = mExtractor.read(mExtractorInput, mPositionHolder);
- } catch (ParserException e) {
- throw new ParsingException(e);
+ } catch (Exception e) {
+ mLastObservedExceptionName = e.getClass().getName();
+ if (e instanceof ParserException) {
+ throw new ParsingException((ParserException) e);
+ } else {
+ throw e;
+ }
}
if (result == Extractor.RESULT_END_OF_INPUT) {
mExtractorInput = null;
@@ -1264,21 +1295,64 @@ public final class MediaParser {
* invoked.
*/
public void release() {
- // TODO: Dump media metrics here.
mExtractorInput = null;
mExtractor = null;
+ if (mReleased) {
+ // Nothing to do.
+ return;
+ }
+ mReleased = true;
+
+ String trackMimeTypes = buildMediaMetricsString(format -> format.sampleMimeType);
+ String trackCodecs = buildMediaMetricsString(format -> format.codecs);
+ int videoWidth = -1;
+ int videoHeight = -1;
+ for (int i = 0; i < mTrackFormats.size(); i++) {
+ Format format = mTrackFormats.valueAt(i);
+ if (format.width != Format.NO_VALUE && format.height != Format.NO_VALUE) {
+ videoWidth = format.width;
+ videoHeight = format.height;
+ break;
+ }
+ }
+
+ String alteredParameters =
+ String.join(
+ MEDIAMETRICS_ELEMENT_SEPARATOR,
+ mParserParameters.keySet().toArray(new String[0]));
+ alteredParameters =
+ alteredParameters.substring(
+ 0,
+ Math.min(
+ alteredParameters.length(),
+ MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH));
+
+ nativeSubmitMetrics(
+ mParserName,
+ mCreatedByName,
+ String.join(MEDIAMETRICS_ELEMENT_SEPARATOR, mParserNamesPool),
+ mLastObservedExceptionName,
+ addDither(mResourceByteCount),
+ addDither(mDurationMillis),
+ trackMimeTypes,
+ trackCodecs,
+ alteredParameters,
+ videoWidth,
+ videoHeight);
}
// Private methods.
- private MediaParser(OutputConsumer outputConsumer, boolean sniff, String... parserNamesPool) {
+ private MediaParser(
+ OutputConsumer outputConsumer, boolean createdByName, String... parserNamesPool) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
throw new UnsupportedOperationException("Android version must be R or greater.");
}
mParserParameters = new HashMap<>();
mOutputConsumer = outputConsumer;
mParserNamesPool = parserNamesPool;
- mParserName = sniff ? PARSER_NAME_UNKNOWN : parserNamesPool[0];
+ mCreatedByName = createdByName;
+ mParserName = createdByName ? parserNamesPool[0] : PARSER_NAME_UNKNOWN;
mPositionHolder = new PositionHolder();
mExoDataReader = new InputReadingDataReader();
removePendingSeek();
@@ -1286,6 +1360,24 @@ public final class MediaParser {
mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
mSchemeInitDataConstructor = getSchemeInitDataConstructor();
mMuxedCaptionFormats = new ArrayList<>();
+
+ // MediaMetrics.
+ mTrackFormats = new SparseArray<>();
+ mLastObservedExceptionName = "";
+ mDurationMillis = -1;
+ }
+
+ private String buildMediaMetricsString(Function<Format, String> formatFieldGetter) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < mTrackFormats.size(); i++) {
+ if (i > 0) {
+ stringBuilder.append(MEDIAMETRICS_ELEMENT_SEPARATOR);
+ }
+ String fieldValue = formatFieldGetter.apply(mTrackFormats.valueAt(i));
+ stringBuilder.append(fieldValue != null ? fieldValue : "");
+ }
+ return stringBuilder.substring(
+ 0, Math.min(stringBuilder.length(), MEDIAMETRICS_MAX_STRING_SIZE));
}
private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
@@ -1528,6 +1620,10 @@ public final class MediaParser {
@Override
public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
+ long durationUs = exoplayerSeekMap.getDurationUs();
+ if (durationUs != C.TIME_UNSET) {
+ mDurationMillis = C.usToMs(durationUs);
+ }
if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
MediaFormat mediaFormat = new MediaFormat();
@@ -1575,6 +1671,7 @@ public final class MediaParser {
@Override
public void format(Format format) {
+ mTrackFormats.put(mTrackIndex, format);
mOutputConsumer.onTrackDataFound(
mTrackIndex,
new TrackData(
@@ -2031,6 +2128,20 @@ public final class MediaParser {
return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
}
+ /**
+ * Introduces random error to the given metric value in order to prevent the identification of
+ * the parsed media.
+ */
+ private static long addDither(long value) {
+ // Generate a random in [0, 1].
+ double randomDither = ThreadLocalRandom.current().nextFloat();
+ // Clamp the random number to [0, 2 * MEDIAMETRICS_DITHER].
+ randomDither *= 2 * MEDIAMETRICS_DITHER;
+ // Translate the random number to [1 - MEDIAMETRICS_DITHER, 1 + MEDIAMETRICS_DITHER].
+ randomDither += 1 - MEDIAMETRICS_DITHER;
+ return value != -1 ? (long) (value * randomDither) : -1;
+ }
+
private static void assertValidNames(@NonNull String[] names) {
for (String name : names) {
if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
@@ -2070,9 +2181,26 @@ public final class MediaParser {
}
}
+ // Native methods.
+
+ private native void nativeSubmitMetrics(
+ String parserName,
+ boolean createdByName,
+ String parserPool,
+ String lastObservedExceptionName,
+ long resourceByteCount,
+ long durationMillis,
+ String trackMimeTypes,
+ String trackCodecs,
+ String alteredParameters,
+ int videoWidth,
+ int videoHeight);
+
// Static initialization.
static {
+ System.loadLibrary(JNI_LIBRARY_NAME);
+
// Using a LinkedHashMap to keep the insertion order when iterating over the keys.
LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
// Parsers are ordered to match ExoPlayer's DefaultExtractorsFactory extractor ordering,
@@ -2125,6 +2253,15 @@ public final class MediaParser {
// We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
// instead. Checking that the value is a List is insufficient to catch wrong parameter
// value types.
+ int sumOfParameterNameLengths =
+ expectedTypeByParameterName.keySet().stream()
+ .map(String::length)
+ .reduce(0, Integer::sum);
+ sumOfParameterNameLengths += PARAMETER_EXPOSE_CAPTION_FORMATS.length();
+ // Add space for any required separators.
+ MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH =
+ sumOfParameterNameLengths + expectedTypeByParameterName.size();
+
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
}
}
diff --git a/apex/media/framework/jni/android_media_MediaParserJNI.cpp b/apex/media/framework/jni/android_media_MediaParserJNI.cpp
new file mode 100644
index 000000000000..7fc4628984f5
--- /dev/null
+++ b/apex/media/framework/jni/android_media_MediaParserJNI.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright 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.
+ */
+
+#include <jni.h>
+#include <media/MediaMetrics.h>
+
+#define JNI_FUNCTION(RETURN_TYPE, NAME, ...) \
+ extern "C" { \
+ JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
+ ##__VA_ARGS__); \
+ } \
+ JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
+ ##__VA_ARGS__)
+
+namespace {
+
+constexpr char kMediaMetricsKey[] = "mediaparser";
+
+constexpr char kAttributeParserName[] = "android.media.mediaparser.parserName";
+constexpr char kAttributeCreatedByName[] = "android.media.mediaparser.createdByName";
+constexpr char kAttributeParserPool[] = "android.media.mediaparser.parserPool";
+constexpr char kAttributeLastException[] = "android.media.mediaparser.lastException";
+constexpr char kAttributeResourceByteCount[] = "android.media.mediaparser.resourceByteCount";
+constexpr char kAttributeDurationMillis[] = "android.media.mediaparser.durationMillis";
+constexpr char kAttributeTrackMimeTypes[] = "android.media.mediaparser.trackMimeTypes";
+constexpr char kAttributeTrackCodecs[] = "android.media.mediaparser.trackCodecs";
+constexpr char kAttributeAlteredParameters[] = "android.media.mediaparser.alteredParameters";
+constexpr char kAttributeVideoWidth[] = "android.media.mediaparser.videoWidth";
+constexpr char kAttributeVideoHeight[] = "android.media.mediaparser.videoHeight";
+
+// Util class to handle string resource management.
+class JstringHandle {
+public:
+ JstringHandle(JNIEnv* env, jstring value) : mEnv(env), mJstringValue(value) {
+ mCstringValue = env->GetStringUTFChars(value, /* isCopy= */ nullptr);
+ }
+
+ ~JstringHandle() {
+ if (mCstringValue != nullptr) {
+ mEnv->ReleaseStringUTFChars(mJstringValue, mCstringValue);
+ }
+ }
+
+ [[nodiscard]] const char* value() const {
+ return mCstringValue != nullptr ? mCstringValue : "";
+ }
+
+ JNIEnv* mEnv;
+ jstring mJstringValue;
+ const char* mCstringValue;
+};
+
+} // namespace
+
+JNI_FUNCTION(void, nativeSubmitMetrics, jstring parserNameJstring, jboolean createdByName,
+ jstring parserPoolJstring, jstring lastExceptionJstring, jlong resourceByteCount,
+ jlong durationMillis, jstring trackMimeTypesJstring, jstring trackCodecsJstring,
+ jstring alteredParameters, jint videoWidth, jint videoHeight) {
+ mediametrics_handle_t item(mediametrics_create(kMediaMetricsKey));
+ mediametrics_setCString(item, kAttributeParserName,
+ JstringHandle(env, parserNameJstring).value());
+ mediametrics_setInt32(item, kAttributeCreatedByName, createdByName ? 1 : 0);
+ mediametrics_setCString(item, kAttributeParserPool,
+ JstringHandle(env, parserPoolJstring).value());
+ mediametrics_setCString(item, kAttributeLastException,
+ JstringHandle(env, lastExceptionJstring).value());
+ mediametrics_setInt64(item, kAttributeResourceByteCount, resourceByteCount);
+ mediametrics_setInt64(item, kAttributeDurationMillis, durationMillis);
+ mediametrics_setCString(item, kAttributeTrackMimeTypes,
+ JstringHandle(env, trackMimeTypesJstring).value());
+ mediametrics_setCString(item, kAttributeTrackCodecs,
+ JstringHandle(env, trackCodecsJstring).value());
+ mediametrics_setCString(item, kAttributeAlteredParameters,
+ JstringHandle(env, alteredParameters).value());
+ mediametrics_setInt32(item, kAttributeVideoWidth, videoWidth);
+ mediametrics_setInt32(item, kAttributeVideoHeight, videoHeight);
+ mediametrics_selfRecord(item);
+ mediametrics_delete(item);
+}
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index dc1612575f38..13bf197aa9dc 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -554,6 +554,10 @@ status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8
return NO_ERROR;
}
if (!args[0].compare(String8("section"))) {
+ if (argCount == 1) {
+ fprintf(out, "Not enough arguments for section\n");
+ return NO_ERROR;
+ }
int id = atoi(args[1]);
int idx = 0;
while (SECTION_LIST[idx] != NULL) {
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 38d378169ec9..3e21e149b3b6 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -364,6 +364,18 @@ public class AccessibilityServiceInfo implements Parcelable {
*/
public static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x0001000;
+ /**
+ * This flag requests that when when {@link #FLAG_REQUEST_MULTI_FINGER_GESTURES} is enabled,
+ * two-finger passthrough gestures are re-enabled. Two-finger swipe gestures are not detected,
+ * but instead passed through as one-finger gestures. In addition, three-finger swipes from the
+ * bottom of the screen are not detected, and instead are passed through unchanged. If {@link
+ * #FLAG_REQUEST_MULTI_FINGER_GESTURES} is disabled this flag has no effect.
+ *
+ * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
+ * @hide
+ */
+ public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
+
/** {@hide} */
public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
@@ -1261,6 +1273,8 @@ public class AccessibilityServiceInfo implements Parcelable {
return "FLAG_SERVICE_HANDLES_DOUBLE_TAP";
case FLAG_REQUEST_MULTI_FINGER_GESTURES:
return "FLAG_REQUEST_MULTI_FINGER_GESTURES";
+ case FLAG_REQUEST_2_FINGER_PASSTHROUGH:
+ return "FLAG_REQUEST_2_FINGER_PASSTHROUGH";
case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
case FLAG_REPORT_VIEW_IDS:
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index af74b036a796..5dc6e602e5d6 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -16,16 +16,23 @@
package android.accounts;
import android.app.Activity;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.widget.TextView;
-import android.widget.LinearLayout;
-import android.view.View;
-import android.view.LayoutInflater;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
import com.android.internal.R;
import java.io.IOException;
@@ -42,11 +49,15 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
private Account mAccount;
private String mAuthTokenType;
private int mUid;
+ private int mCallingUid;
private Bundle mResultBundle = null;
protected LayoutInflater mInflater;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().addSystemFlags(
+ android.view.WindowManager.LayoutParams
+ .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
setContentView(R.layout.grant_credentials_permission);
setTitle(R.string.grant_permissions_header_text);
@@ -74,6 +85,20 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
return;
}
+ try {
+ IBinder activityToken = getActivityToken();
+ mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken);
+ } catch (RemoteException re) {
+ // Couldn't figure out caller details
+ Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
+ }
+
+ if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ return;
+ }
+
String accountTypeLabel;
try {
accountTypeLabel = getAccountLabel(mAccount);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 80d2e6c60f69..4aedfeefb72b 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1275,10 +1275,10 @@ public class ActivityOptions {
}
/**
- * Sets the id of the display where activity should be launched.
- * An app can launch activities on public displays or private displays that are owned by the app
- * or where an app already has activities. Otherwise, trying to launch on a private display
- * or providing an invalid display id will result in an exception.
+ * Sets the id of the display where the activity should be launched.
+ * An app can launch activities on public displays or displays where the app already has
+ * activities. Otherwise, trying to launch on a private display or providing an invalid display
+ * id will result in an exception.
* <p>
* Setting launch display id will be ignored on devices that don't have
* {@link android.content.pm.PackageManager#FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS}.
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 92b0da1c761f..098d090b5e30 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -105,7 +105,8 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
public ActivityView(
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
- this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay, false);
+ this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay,
+ false /* disableSurfaceViewBackgroundLayer */);
}
/** @hide */
@@ -113,12 +114,22 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
boolean singleTaskInstance, boolean usePublicVirtualDisplay,
boolean disableSurfaceViewBackgroundLayer) {
+ this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay,
+ disableSurfaceViewBackgroundLayer, false /* useTrustedDisplay */);
+ }
+
+ // TODO(b/162901735): Refactor ActivityView with Builder
+ /** @hide */
+ public ActivityView(
+ @NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
+ boolean singleTaskInstance, boolean usePublicVirtualDisplay,
+ boolean disableSurfaceViewBackgroundLayer, boolean useTrustedDisplay) {
super(context, attrs, defStyle);
if (useTaskOrganizer()) {
mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
} else {
mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, singleTaskInstance,
- usePublicVirtualDisplay);
+ usePublicVirtualDisplay, useTrustedDisplay);
}
mSurfaceView = new SurfaceView(context, null, 0, 0, disableSurfaceViewBackgroundLayer);
// Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 31ab2248236d..ba547b74f106 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -31,8 +31,10 @@ import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.database.DatabaseUtils;
@@ -52,6 +54,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseArray;
@@ -1137,7 +1140,7 @@ public class AppOpsManager {
public static final int OP_RECORD_AUDIO_HOTWORD = 102;
/** @hide */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int _NUM_OP = 104;
/** Access to coarse location information. */
@@ -7610,8 +7613,9 @@ public class AppOpsManager {
collectNotedOpForSelf(op, proxiedAttributionTag);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
- && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
- myUid) == PackageManager.PERMISSION_GRANTED) {
+ && (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
+ myUid) == PackageManager.PERMISSION_GRANTED
+ || isTrustedVoiceServiceProxy(mContext, mContext.getOpPackageName(), op))) {
collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7623,6 +7627,43 @@ public class AppOpsManager {
}
/**
+ * Checks if the voice recognition service is a trust proxy.
+ *
+ * @return {@code true} if the package is a trust voice recognition service proxy
+ * @hide
+ */
+ public static boolean isTrustedVoiceServiceProxy(Context context, String packageName,
+ int code) {
+ // This is a workaround for R QPR, new API change is not allowed. We only allow the current
+ // voice recognizer is also the voice interactor to noteproxy op.
+ if (code != OP_RECORD_AUDIO) {
+ return false;
+ }
+ final String voiceRecognitionComponent = Settings.Secure.getString(
+ context.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
+
+ final String voiceRecognitionServicePackageName =
+ getComponentPackageNameFromString(voiceRecognitionComponent);
+ return (Objects.equals(packageName, voiceRecognitionServicePackageName))
+ && isPackagePreInstalled(context, packageName);
+ }
+
+ private static String getComponentPackageNameFromString(String from) {
+ ComponentName componentName = from != null ? ComponentName.unflattenFromString(from) : null;
+ return componentName != null ? componentName.getPackageName() : "";
+ }
+
+ private static boolean isPackagePreInstalled(Context context, String packageName) {
+ try {
+ final PackageManager pm = context.getPackageManager();
+ final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ return ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
* String, String)} or {@link #startOp(int, int, String, boolean, String, String)} for your
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 7be661b957c0..b45f3893db8c 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -286,7 +286,7 @@ public final class LoadedApk {
return mSecurityViolation;
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public CompatibilityInfo getCompatibilityInfo() {
return mDisplayAdjustments.getCompatibilityInfo();
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6edc8ea6a3a6..2f99cf107754 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4261,6 +4261,9 @@ public class DevicePolicyManager {
* This method can be called on the {@link DevicePolicyManager} instance returned by
* {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile.
* <p>
+ * NOTE: on {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}, this
+ * method doesn't turn off the screen as it would be a driving safety distraction.
+ * <p>
* Equivalent to calling {@link #lockNow(int)} with no flags.
*
* @throws SecurityException if the calling application does not own an active administrator
@@ -4304,6 +4307,9 @@ public class DevicePolicyManager {
* Calling the method twice in this order ensures that all users are locked and does not
* stop the device admin on the managed profile from issuing a second call to lock its own
* profile.
+ * <p>
+ * NOTE: on {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE automotive builds}, this
+ * method doesn't turn off the screen as it would be a driving safety distraction.
*
* @param flags May be 0 or {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}.
* @throws SecurityException if the calling application does not own an active administrator
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index bd1eea51f8af..46be54814dc9 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -153,6 +153,7 @@ public abstract class SliceProvider extends ContentProvider {
*/
public static final String EXTRA_PKG = "pkg";
/**
+ * @Deprecated provider pkg is now being extracted in SlicePermissionActivity
* @hide
*/
public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 7b567b4098e7..f43a9e8cab9d 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,7 +40,7 @@ public final class BluetoothCodecStatus implements Parcelable {
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final String EXTRA_CODEC_STATUS =
"android.bluetooth.extra.CODEC_STATUS";
@@ -198,7 +199,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return the current codec configuration
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
@@ -208,7 +209,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs local capabilities
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
return mCodecsLocalCapabilities;
}
@@ -218,7 +219,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs selectable capabilities
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
return mCodecsSelectableCapabilities;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index adb7e2f773a9..57d1411aa68a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -80,7 +80,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
/**
* Intent used to broadcast the change in the Audio Connection state of the
- * A2DP profile.
+ * HDP profile.
*
* <p>This intent will have 3 extras:
* <ul>
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 7733dc14ace4..903d1296fb87 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -47,6 +47,7 @@ public final class AssociationRequest implements Parcelable {
private final boolean mSingleDevice;
private final List<DeviceFilter<?>> mDeviceFilters;
+ private String mCallingPackage;
private AssociationRequest(
boolean singleDevice, @Nullable List<DeviceFilter<?>> deviceFilters) {
@@ -58,6 +59,7 @@ public final class AssociationRequest implements Parcelable {
this(
in.readByte() != 0,
in.readParcelableList(new ArrayList<>(), AssociationRequest.class.getClassLoader()));
+ setCallingPackage(in.readString());
}
/** @hide */
@@ -73,32 +75,45 @@ public final class AssociationRequest implements Parcelable {
return mDeviceFilters;
}
+ /** @hide */
+ public String getCallingPackage() {
+ return mCallingPackage;
+ }
+
+ /** @hide */
+ public void setCallingPackage(String pkg) {
+ mCallingPackage = pkg;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AssociationRequest that = (AssociationRequest) o;
- return mSingleDevice == that.mSingleDevice &&
- Objects.equals(mDeviceFilters, that.mDeviceFilters);
+ return mSingleDevice == that.mSingleDevice
+ && Objects.equals(mDeviceFilters, that.mDeviceFilters)
+ && Objects.equals(mCallingPackage, that.mCallingPackage);
}
@Override
public int hashCode() {
- return Objects.hash(mSingleDevice, mDeviceFilters);
+ return Objects.hash(mSingleDevice, mDeviceFilters, mCallingPackage);
}
@Override
public String toString() {
- return "AssociationRequest{" +
- "mSingleDevice=" + mSingleDevice +
- ", mDeviceFilters=" + mDeviceFilters +
- '}';
+ return "AssociationRequest{"
+ + "mSingleDevice=" + mSingleDevice
+ + ", mDeviceFilters=" + mDeviceFilters
+ + ", mCallingPackage=" + mCallingPackage
+ + '}';
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mSingleDevice ? 1 : 0));
dest.writeParcelableList(mDeviceFilters, flags);
+ dest.writeString(mCallingPackage);
}
@Override
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 8b411d5fe031..b290679c9fcc 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -119,8 +119,9 @@ public class CrossProfileApps {
* {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
* {@link SecurityException} will be thrown.
* @param callingActivity The activity to start the new activity from for the purposes of
- * deciding which task the new activity should belong to. If {@code null}, the activity
- * will always be started in a new task.
+ * passing back any result and deciding which task the new activity should belong to. If
+ * {@code null}, the activity will always be started in a new task and no result will be
+ * returned.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.INTERACT_ACROSS_PROFILES,
@@ -146,8 +147,9 @@ public class CrossProfileApps {
* {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
* {@link SecurityException} will be thrown.
* @param callingActivity The activity to start the new activity from for the purposes of
- * deciding which task the new activity should belong to. If {@code null}, the activity
- * will always be started in a new task.
+ * passing back any result and deciding which task the new activity should belong to. If
+ * {@code null}, the activity will always be started in a new task and no result will be
+ * returned.
* @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
*/
@RequiresPermission(anyOf = {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 50ef08a9598a..1d914bbc3e33 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -92,6 +92,11 @@ import java.util.Set;
* packages that are currently installed on the device.
*
* You can find this class through {@link Context#getPackageManager}.
+ *
+ * <p class="note"><strong>Note: </strong>If your app targets Android 11 (API level 30) or
+ * higher, the methods in this class each return a filtered list of apps. Learn more about how to
+ * <a href="/training/basics/intents/package-visibility">manage package visibility</a>.
+ * </p>
*/
public abstract class PackageManager {
private static final String TAG = "PackageManager";
@@ -1686,6 +1691,15 @@ public abstract class PackageManager {
public static final int DELETE_FAILED_USED_SHARED_LIBRARY = -6;
/**
+ * Deletion failed return code: this is passed to the
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * because there is an app pinned.
+ *
+ * @hide
+ */
+ public static final int DELETE_FAILED_APP_PINNED = -7;
+
+ /**
* Return code that is passed to the {@link IPackageMoveObserver} when the
* package has been successfully moved by the system.
*
@@ -7622,6 +7636,7 @@ public abstract class PackageManager {
case DELETE_FAILED_OWNER_BLOCKED: return "DELETE_FAILED_OWNER_BLOCKED";
case DELETE_FAILED_ABORTED: return "DELETE_FAILED_ABORTED";
case DELETE_FAILED_USED_SHARED_LIBRARY: return "DELETE_FAILED_USED_SHARED_LIBRARY";
+ case DELETE_FAILED_APP_PINNED: return "DELETE_FAILED_APP_PINNED";
default: return Integer.toString(status);
}
}
@@ -7636,6 +7651,7 @@ public abstract class PackageManager {
case DELETE_FAILED_OWNER_BLOCKED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
case DELETE_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED;
case DELETE_FAILED_USED_SHARED_LIBRARY: return PackageInstaller.STATUS_FAILURE_CONFLICT;
+ case DELETE_FAILED_APP_PINNED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
default: return PackageInstaller.STATUS_FAILURE;
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4f3c0cb029b8..32aa1c2ed7aa 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2772,7 +2772,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* </ol>
* </li>
* <li>Setting {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} to values different than 1.0 and
- * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be windowboxing at the same time is undefined behavior.</li>
+ * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be windowboxing at the same time are not supported. In this
+ * case, the camera framework will override the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be the active
+ * array.</li>
* </ul>
* <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
* <p><b>Possible values:</b>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index cd137078818c..37e12809467d 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -234,7 +234,7 @@ public abstract class CameraDevice implements AutoCloseable {
* @see StreamConfigurationMap#getOutputFormats()
* @see StreamConfigurationMap#getOutputSizes(int)
* @see StreamConfigurationMap#getOutputSizes(Class)
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
*/
@@ -249,7 +249,7 @@ public abstract class CameraDevice implements AutoCloseable {
*
* @see #createCaptureSession
* @see OutputConfiguration
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
*/
@@ -285,7 +285,7 @@ public abstract class CameraDevice implements AutoCloseable {
* @see StreamConfigurationMap#getOutputSizes
* @see android.media.ImageWriter
* @see android.media.ImageReader
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
*/
@@ -302,7 +302,7 @@ public abstract class CameraDevice implements AutoCloseable {
*
* @see #createReprocessableCaptureSession
* @see OutputConfiguration
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
*/
@@ -340,7 +340,7 @@ public abstract class CameraDevice implements AutoCloseable {
* @see CameraCaptureSession#captureBurst
* @see CameraCaptureSession#setRepeatingBurst
* @see CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
*/
@@ -413,7 +413,7 @@ public abstract class CameraDevice implements AutoCloseable {
* @see #createReprocessableCaptureSession
* @see CameraCaptureSession
* @see OutputConfiguration
- * @deprecated Please use @{link
+ * @deprecated Please use {@link
* #createCaptureSession(android.hardware.camera2.params.SessionConfiguration)} for the
* full set of configuration options available.
* @hide
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 2b633b5c5643..66e78bbc2f22 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2243,7 +2243,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* explicitly set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, its value defaults to 1.0.</p>
* <p>One limitation of controlling zoom using zoomRatio is that the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
* must only be used for letterboxing or pillarboxing of the sensor active array, and no
- * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0.</p>
+ * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0. If
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is not 1.0, and {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is set to be
+ * windowboxing, the camera framework will override the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be
+ * the active array.</p>
* <p><b>Range of valid values:</b><br>
* {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 41f4df7dbc99..ded7c8a8777e 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2473,7 +2473,10 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* explicitly set {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}, its value defaults to 1.0.</p>
* <p>One limitation of controlling zoom using zoomRatio is that the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}
* must only be used for letterboxing or pillarboxing of the sensor active array, and no
- * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0.</p>
+ * FREEFORM cropping can be used with {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} other than 1.0. If
+ * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} is not 1.0, and {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is set to be
+ * windowboxing, the camera framework will override the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to be
+ * the active array.</p>
* <p><b>Range of valid values:</b><br>
* {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE android.control.zoomRatioRange}</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 920d34f09819..19f4cd6e991a 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -73,6 +73,7 @@ import android.util.Range;
import android.util.Size;
import dalvik.annotation.optimization.FastNative;
+import dalvik.system.VMRuntime;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -352,6 +353,7 @@ public class CameraMetadataNative implements Parcelable {
if (mMetadataPtr == 0) {
throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
}
+ updateNativeAllocation();
}
/**
@@ -363,6 +365,7 @@ public class CameraMetadataNative implements Parcelable {
if (mMetadataPtr == 0) {
throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
}
+ updateNativeAllocation();
}
/**
@@ -444,6 +447,7 @@ public class CameraMetadataNative implements Parcelable {
public void readFromParcel(Parcel in) {
nativeReadFromParcel(in, mMetadataPtr);
+ updateNativeAllocation();
}
/**
@@ -534,6 +538,11 @@ public class CameraMetadataNative implements Parcelable {
// Delete native pointer, but does not clear it
nativeClose(mMetadataPtr);
mMetadataPtr = 0;
+
+ if (mBufferSize > 0) {
+ VMRuntime.getRuntime().registerNativeFree(mBufferSize);
+ }
+ mBufferSize = 0;
}
private <T> T getBase(CameraCharacteristics.Key<T> key) {
@@ -1646,9 +1655,26 @@ public class CameraMetadataNative implements Parcelable {
return true;
}
+ private void updateNativeAllocation() {
+ long currentBufferSize = nativeGetBufferSize(mMetadataPtr);
+
+ if (currentBufferSize != mBufferSize) {
+ if (mBufferSize > 0) {
+ VMRuntime.getRuntime().registerNativeFree(mBufferSize);
+ }
+
+ mBufferSize = currentBufferSize;
+
+ if (mBufferSize > 0) {
+ VMRuntime.getRuntime().registerNativeAllocation(mBufferSize);
+ }
+ }
+ }
+
private int mCameraId = -1;
private boolean mHasMandatoryConcurrentStreams = false;
private Size mDisplaySize = new Size(0, 0);
+ private long mBufferSize = 0;
/**
* Set the current camera Id.
@@ -1706,6 +1732,8 @@ public class CameraMetadataNative implements Parcelable {
private static synchronized native boolean nativeIsEmpty(long ptr);
@FastNative
private static synchronized native int nativeGetEntryCount(long ptr);
+ @FastNative
+ private static synchronized native long nativeGetBufferSize(long ptr);
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@FastNative
@@ -1745,6 +1773,8 @@ public class CameraMetadataNative implements Parcelable {
mCameraId = other.mCameraId;
mHasMandatoryConcurrentStreams = other.mHasMandatoryConcurrentStreams;
mDisplaySize = other.mDisplaySize;
+ updateNativeAllocation();
+ other.updateNativeAllocation();
}
/**
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 9271d0e05fa0..7a383d993389 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -870,38 +870,77 @@ public final class DisplayManager {
public interface DeviceConfig {
/**
- * Key for refresh rate in the zone defined by thresholds.
+ * Key for refresh rate in the low zone defined by thresholds.
*
+ * Note that the name and value don't match because they were added before we had a high
+ * zone to consider.
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
* @see android.R.integer#config_defaultZoneBehavior
*/
- String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
+ String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone";
/**
- * Key for accessing the display brightness thresholds for the configured refresh rate zone.
+ * Key for accessing the low display brightness thresholds for the configured refresh
+ * rate zone.
* The value will be a pair of comma separated integers representing the minimum and maximum
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
*
+ * Note that the name and value don't match because they were added before we had a high
+ * zone to consider.
+ *
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
* @hide
*/
- String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
+ String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS =
"peak_refresh_rate_brightness_thresholds";
/**
- * Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
- * The value will be a pair of comma separated integers representing the minimum and maximum
- * thresholds of the zone, respectively, in lux.
+ * Key for accessing the low ambient brightness thresholds for the configured refresh
+ * rate zone. The value will be a pair of comma separated integers representing the minimum
+ * and maximum thresholds of the zone, respectively, in lux.
+ *
+ * Note that the name and value don't match because they were added before we had a high
+ * zone to consider.
*
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
* @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
* @hide
*/
- String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
+ String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS =
"peak_refresh_rate_ambient_thresholds";
+ /**
+ * Key for refresh rate in the high zone defined by thresholds.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+ * @see android.R.integer#config_fixedRefreshRateInHighZone
+ */
+ String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone";
/**
+ * Key for accessing the display brightness thresholds for the configured refresh rate zone.
+ * The value will be a pair of comma separated integers representing the minimum and maximum
+ * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+ * @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate
+ * @hide
+ */
+ String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS =
+ "fixed_refresh_rate_high_display_brightness_thresholds";
+
+ /**
+ * Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
+ * The value will be a pair of comma separated integers representing the minimum and maximum
+ * thresholds of the zone, respectively, in lux.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+ * @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate
+ * @hide
+ */
+ String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
+ "fixed_refresh_rate_high_ambient_brightness_thresholds";
+ /**
* Key for default peak refresh rate
*
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 527495edce67..40c3d87e4f36 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -16,11 +16,11 @@
package android.inputmethodservice;
-import static android.graphics.Color.TRANSPARENT;
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;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -69,7 +69,9 @@ import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
@@ -103,7 +105,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
+import java.util.ArrayList;
/**
* InputMethodService provides a standard implementation of an InputMethod,
@@ -849,10 +851,19 @@ public class InputMethodService extends AbstractInputMethodService {
/** Set region of the keyboard to be avoided from back gesture */
private void setImeExclusionRect(int visibleTopInsets) {
- View inputFrameRootView = mInputFrame.getRootView();
- Rect r = new Rect(0, visibleTopInsets, inputFrameRootView.getWidth(),
- inputFrameRootView.getHeight());
- inputFrameRootView.setSystemGestureExclusionRects(Collections.singletonList(r));
+ View rootView = mInputFrame.getRootView();
+ android.graphics.Insets systemGesture =
+ rootView.getRootWindowInsets().getInsetsIgnoringVisibility(Type.systemGestures());
+ ArrayList<Rect> exclusionRects = new ArrayList<>();
+ exclusionRects.add(new Rect(0,
+ visibleTopInsets,
+ systemGesture.left,
+ rootView.getHeight()));
+ exclusionRects.add(new Rect(rootView.getWidth() - systemGesture.right,
+ visibleTopInsets,
+ rootView.getWidth(),
+ rootView.getHeight()));
+ rootView.setSystemGestureExclusionRects(exclusionRects);
}
/**
@@ -1202,22 +1213,24 @@ public class InputMethodService extends AbstractInputMethodService {
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
- mWindow.getWindow().getAttributes().setFitInsetsTypes(navigationBars());
+ mWindow.getWindow().getAttributes().setFitInsetsTypes(statusBars() | navigationBars());
mWindow.getWindow().getAttributes().setFitInsetsSides(Side.all() & ~Side.BOTTOM);
- mWindow.getWindow().getAttributes().setFitInsetsIgnoringVisibility(true);
- // Our window will extend into the status bar area no matter the bar is visible or not.
- // We don't want the ColorView to be visible when status bar is shown.
- mWindow.getWindow().setStatusBarColor(TRANSPARENT);
-
- // Automotive devices may request the navigation bar to be hidden when the IME shows up
- // (controlled via config_automotiveHideNavBarForKeyboard) in order to maximize the visible
- // screen real estate. When this happens, the IME window should animate from the bottom of
- // the screen to reduce the jank that happens from the lack of synchronization between the
- // bottom system window and the IME window.
+ // IME layout should always be inset by navigation bar, no matter its current visibility,
+ // unless automotive requests it. Automotive devices may request the navigation bar to be
+ // hidden when the IME shows up (controlled via config_automotiveHideNavBarForKeyboard)
+ // in order to maximize the visible screen real estate. When this happens, the IME window
+ // should animate from the bottom of the screen to reduce the jank that happens from the
+ // lack of synchronization between the bottom system window and the IME window.
if (mIsAutomotive && mAutomotiveHideNavBarForKeyboard) {
mWindow.getWindow().setDecorFitsSystemWindows(false);
}
+ mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
+ (v, insets) -> v.onApplyWindowInsets(
+ new WindowInsets.Builder(insets).setInsets(
+ navigationBars(),
+ insets.getInsetsIgnoringVisibility(navigationBars()))
+ .build()));
// For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
// by default (but IME developers can opt this out later if they want a new behavior).
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index d23d2eca7603..dfc9d5dc0deb 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -94,6 +94,8 @@ interface IPowerManager
boolean isAmbientDisplaySuppressedForToken(String token);
// returns whether ambient display is suppressed by any app with any token.
boolean isAmbientDisplaySuppressed();
+ // returns whether ambient display is suppressed by the given app with the given token.
+ boolean isAmbientDisplaySuppressedForTokenByApp(String token, int appUid);
// Forces the system to suspend even if there are held wakelocks.
boolean forceSuspend();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 49b4e0024fc2..bfbdf62d39bb 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2121,6 +2121,27 @@ public final class PowerManager {
}
/**
+ * Returns true if ambient display is suppressed by the given {@code appUid} with the given
+ * {@code token}.
+ *
+ * <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
+ *
+ * @param token The identifier of the ambient display suppression.
+ * @param appUid The uid of the app that suppressed ambient display.
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.READ_DREAM_STATE,
+ android.Manifest.permission.READ_DREAM_SUPPRESSION })
+ public boolean isAmbientDisplaySuppressedForTokenByApp(@NonNull String token, int appUid) {
+ try {
+ return mService.isAmbientDisplaySuppressedForTokenByApp(token, appUid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns the reason the phone was last shutdown. Calling app must have the
* {@link android.Manifest.permission#DEVICE_POWER} permission to request this information.
* @return Reason for shutdown as an int, {@link #SHUTDOWN_REASON_UNKNOWN} if the file could
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 1a59e8d34547..b704d66d8e41 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -218,8 +218,15 @@ public abstract class DocumentsProvider extends ContentProvider {
}
/** {@hide} */
- private void enforceTree(Uri documentUri) {
- if (isTreeUri(documentUri)) {
+ private void enforceTreeForExtraUris(Bundle extras) {
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI));
+ }
+
+ /** {@hide} */
+ private void enforceTree(@Nullable Uri documentUri) {
+ if (documentUri != null && isTreeUri(documentUri)) {
final String parent = getTreeDocumentId(documentUri);
final String child = getDocumentId(documentUri);
if (Objects.equals(parent, child)) {
@@ -232,6 +239,10 @@ public abstract class DocumentsProvider extends ContentProvider {
}
}
+ private Uri validateIncomingNullableUri(@Nullable Uri uri) {
+ return uri == null ? null : validateIncomingUri(uri);
+ }
+
/**
* Create a new document and return its newly generated
* {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
@@ -1076,11 +1087,21 @@ public abstract class DocumentsProvider extends ContentProvider {
final Context context = getContext();
final Bundle out = new Bundle();
+ // If the URI is a tree URI performs some validation.
+ enforceTreeForExtraUris(extras);
+
+ final Uri extraUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_URI));
+ final Uri extraTargetUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI));
+ final Uri extraParentUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI));
+
if (METHOD_EJECT_ROOT.equals(method)) {
// Given that certain system apps can hold MOUNT_UNMOUNT permission, but only apps
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
// MANAGE_DOCUMENTS or associated URI permission here instead
- final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+ final Uri rootUri = extraUri;
enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(),
null);
@@ -1090,7 +1111,7 @@ public abstract class DocumentsProvider extends ContentProvider {
return out;
}
- final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+ final Uri documentUri = extraUri;
final String authority = documentUri.getAuthority();
final String documentId = DocumentsContract.getDocumentId(documentUri);
@@ -1099,14 +1120,11 @@ public abstract class DocumentsProvider extends ContentProvider {
"Requested authority " + authority + " doesn't match provider " + mAuthority);
}
- // If the URI is a tree URI performs some validation.
- enforceTree(documentUri);
-
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
enforceReadPermissionInner(documentUri, getCallingPackage(),
getCallingAttributionTag(), null);
- final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri childUri = extraTargetUri;
final String childAuthority = childUri.getAuthority();
final String childId = DocumentsContract.getDocumentId(childUri);
@@ -1173,7 +1191,7 @@ public abstract class DocumentsProvider extends ContentProvider {
revokeDocumentPermission(documentId);
} else if (METHOD_COPY_DOCUMENT.equals(method)) {
- final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
enforceReadPermissionInner(documentUri, getCallingPackage(),
@@ -1197,9 +1215,9 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_MOVE_DOCUMENT.equals(method)) {
- final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
+ final Uri parentSourceUri = extraParentUri;
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
- final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
enforceWritePermissionInner(documentUri, getCallingPackage(),
@@ -1225,7 +1243,7 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_REMOVE_DOCUMENT.equals(method)) {
- final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
+ final Uri parentSourceUri = extraParentUri;
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 300bb7603722..6e9cf61968a0 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7884,6 +7884,12 @@ public final class Settings {
public static final String UI_NIGHT_MODE_OVERRIDE_ON = "ui_night_mode_override_on";
/**
+ * The last computed night mode bool the last time the phone was on
+ * @hide
+ */
+ public static final String UI_NIGHT_MODE_LAST_COMPUTED = "ui_night_mode_last_computed";
+
+ /**
* The current night mode that has been overridden to turn off by the system. Owned
* and controlled by UiModeManagerService. Constants are as per
* UiModeManager.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 819462190d9c..81e6d42ec056 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3268,8 +3268,8 @@ public final class ViewRootImpl implements ViewParent,
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
- mImeFocusController.onPostWindowFocus(mView.findFocus(), hasWindowFocus,
- mWindowAttributes);
+ mImeFocusController.onPostWindowFocus(mView != null ? mView.findFocus() : null,
+ hasWindowFocus, mWindowAttributes);
if (hasWindowFocus) {
// Clear the forward bit. We can just do this directly, since
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 3b8368380dda..9d66a21848db 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -199,7 +199,7 @@ import java.util.List;
* <b>Window state changed</b> - represents the event of a change to a section of
* the user interface that is visually distinct. Should be sent from either the
* root view of a window or from a view that is marked as a pane
- * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Not that changes
+ * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Note that changes
* to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br>
* <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
* <em>Properties:</em></br>
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index deed219135ad..22b8ffbd28e3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11009,12 +11009,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
MotionEvent.actionToString(event.getActionMasked()),
event.getX(), event.getY());
}
- if (!isFromPrimePointer(event, false)) {
- return true;
- }
-
final int action = event.getActionMasked();
if (mEditor != null) {
+ if (!isFromPrimePointer(event, false)) {
+ return true;
+ }
+
mEditor.onTouchEvent(event);
if (mEditor.mInsertionPointCursorController != null
diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
index 9ccb4c172158..9013da36007e 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -19,6 +19,7 @@ package android.window;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
import static android.view.Display.INVALID_DISPLAY;
import android.app.ActivityManager;
@@ -63,6 +64,7 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
private int mDisplayDensityDpi;
private final boolean mSingleTaskInstance;
private final boolean mUsePublicVirtualDisplay;
+ private final boolean mUseTrustedDisplay;
private VirtualDisplay mVirtualDisplay;
private Insets mForwardedInsets;
private DisplayMetrics mTmpDisplayMetrics;
@@ -77,10 +79,12 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
* only applicable if virtual displays are used
*/
public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
- boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
+ boolean singleTaskInstance, boolean usePublicVirtualDisplay,
+ boolean useTrustedDisplay) {
super(context, host);
mSingleTaskInstance = singleTaskInstance;
mUsePublicVirtualDisplay = usePublicVirtualDisplay;
+ mUseTrustedDisplay = useTrustedDisplay;
}
/**
@@ -103,6 +107,9 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
if (mUsePublicVirtualDisplay) {
virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_PUBLIC;
}
+ if (mUseTrustedDisplay) {
+ virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_TRUSTED;
+ }
mVirtualDisplay = displayManager.createVirtualDisplay(
DISPLAY_NAME + "@" + System.identityHashCode(this), mHost.getWidth(),
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index ac8f9e8424b7..9679a8cdf735 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1761,7 +1761,7 @@ public class ChooserActivity extends ResolverActivity implements
case ChooserListAdapter.TARGET_CALLER:
case ChooserListAdapter.TARGET_STANDARD:
cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
- value -= currentListAdapter.getSelectableServiceTargetCount();
+ value -= currentListAdapter.getSurfacedTargetInfo().size();
numCallerProvided = currentListAdapter.getCallerTargetCount();
getChooserActivityLogger().logShareTargetSelected(
SELECTION_TYPE_APP,
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index b4cd145ca374..40c21bddf41b 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -428,6 +428,22 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String SCREENSHOT_KEYCHORD_DELAY = "screenshot_keychord_delay";
+ /**
+ * (boolean) Whether to use an ML model for the Back Gesture.
+ */
+ public static final String USE_BACK_GESTURE_ML_MODEL = "use_back_gesture_ml_model";
+
+ /**
+ * (string) The name of the ML model for Back Gesture.
+ */
+ public static final String BACK_GESTURE_ML_MODEL_NAME = "back_gesture_ml_model_name";
+
+ /**
+ * (float) Threshold for Back Gesture ML model prediction.
+ */
+ public static final String BACK_GESTURE_ML_MODEL_THRESHOLD = "back_gesture_ml_model_threshold";
+
+
private SystemUiDeviceConfigFlags() {
}
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 046981cf2e8f..d90a0225608d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1510,11 +1510,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (drawable != mBackgroundDrawable) {
mBackgroundDrawable = drawable;
if (mDecor != null) {
+ mDecor.startChanging();
mDecor.setWindowBackground(drawable);
if (mBackgroundFallbackDrawable != null) {
mDecor.setBackgroundFallback(drawable != null ? null :
mBackgroundFallbackDrawable);
}
+ mDecor.finishChanging();
}
}
}
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 9ad4cd9e9ae8..b5955c4c46cc 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -249,6 +249,16 @@ static jint CameraMetadata_getEntryCount(JNIEnv *env, jclass thiz, jlong ptr) {
return metadata->entryCount();
}
+static jlong CameraMetadata_getBufferSize(JNIEnv *env, jclass thiz, jlong ptr) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
+
+ if (metadata == NULL) return 0;
+
+ return metadata->bufferSize();
+}
+
// idempotent. calling more than once has no effect.
static void CameraMetadata_close(JNIEnv *env, jclass thiz, jlong ptr) {
ALOGV("%s", __FUNCTION__);
@@ -552,6 +562,9 @@ static const JNINativeMethod gCameraMetadataMethods[] = {
{ "nativeGetEntryCount",
"(J)I",
(void*)CameraMetadata_getEntryCount },
+ { "nativeGetBufferSize",
+ "(J)J",
+ (void*)CameraMetadata_getBufferSize },
{ "nativeClose",
"(J)V",
(void*)CameraMetadata_close },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9c65b04d68a1..79f027662994 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -144,7 +144,7 @@
<protected-broadcast android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.UUID" />
<protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
- <protected-broadcast android:name="android.bluetooth.action.ALIAS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
<protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
@@ -4326,6 +4326,10 @@
<permission android:name="android.permission.WRITE_DREAM_STATE"
android:protectionLevel="signature|privileged" />
+ <!-- @hide Allows applications to read whether ambient display is suppressed. -->
+ <permission android:name="android.permission.READ_DREAM_SUPPRESSION"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allow an application to read and write the cache partition.
@hide -->
<permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a1db3bc31e09..f49e2ef11ade 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1224,7 +1224,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>
@@ -1235,7 +1235,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-az/strings.xml b/core/res/res/values-az/strings.xml
index a65f3a3caf59..73adbd86385f 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -687,7 +687,7 @@
<string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"Bəzi ekran kilidi funksiyalarını deaktiv edin"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"Bəzi ekran funksiyaları istifadəsinin qarşısını alın."</string>
<string-array name="phoneTypes">
- <item msgid="8996339953292723951">"Ev"</item>
+ <item msgid="8996339953292723951">"Əsas səhifə"</item>
<item msgid="7740243458912727194">"Mobil"</item>
<item msgid="8526146065496663766">"İş"</item>
<item msgid="8150904584178569699">"İş Faksı"</item>
@@ -697,19 +697,19 @@
<item msgid="6216981255272016212">"Şəxsi"</item>
</string-array>
<string-array name="emailAddressTypes">
- <item msgid="7786349763648997741">"Ev"</item>
+ <item msgid="7786349763648997741">"Ana səhifə"</item>
<item msgid="435564470865989199">"İş"</item>
<item msgid="4199433197875490373">"Digər"</item>
<item msgid="3233938986670468328">"Fərdi"</item>
</string-array>
<string-array name="postalAddressTypes">
- <item msgid="3861463339764243038">"Ev"</item>
+ <item msgid="3861463339764243038">"Əsas səhifə"</item>
<item msgid="5472578890164979109">"İş"</item>
<item msgid="5718921296646594739">"Digər"</item>
<item msgid="5523122236731783179">"Düzənləyin"</item>
</string-array>
<string-array name="imAddressTypes">
- <item msgid="588088543406993772">"Ev"</item>
+ <item msgid="588088543406993772">"Əsas səhifə"</item>
<item msgid="5503060422020476757">"İş"</item>
<item msgid="2530391194653760297">"Digər"</item>
<item msgid="7640927178025203330">"Fərdi"</item>
@@ -755,16 +755,16 @@
<string name="eventTypeAnniversary" msgid="4684702412407916888">"İldönümü"</string>
<string name="eventTypeOther" msgid="530671238533887997">"Digər"</string>
<string name="emailTypeCustom" msgid="1809435350482181786">"Fərdi"</string>
- <string name="emailTypeHome" msgid="1597116303154775999">"Şəxsi"</string>
+ <string name="emailTypeHome" msgid="1597116303154775999">"Əsas səhifə"</string>
<string name="emailTypeWork" msgid="2020095414401882111">"İş"</string>
<string name="emailTypeOther" msgid="5131130857030897465">"Digər"</string>
<string name="emailTypeMobile" msgid="787155077375364230">"Mobil"</string>
<string name="postalTypeCustom" msgid="5645590470242939129">"Fərdi"</string>
- <string name="postalTypeHome" msgid="7562272480949727912">"Ev"</string>
+ <string name="postalTypeHome" msgid="7562272480949727912">"Əsas səhifə"</string>
<string name="postalTypeWork" msgid="8553425424652012826">"İş"</string>
<string name="postalTypeOther" msgid="7094245413678857420">"Digər"</string>
<string name="imTypeCustom" msgid="5653384545085765570">"Fərdi"</string>
- <string name="imTypeHome" msgid="6996507981044278216">"Ev"</string>
+ <string name="imTypeHome" msgid="6996507981044278216">"Ana səhifə"</string>
<string name="imTypeWork" msgid="2099668940169903123">"İş"</string>
<string name="imTypeOther" msgid="8068447383276219810">"Digər"</string>
<string name="imProtocolCustom" msgid="4437878287653764692">"Şəxsi"</string>
@@ -796,7 +796,7 @@
<string name="relationTypeSister" msgid="3721676005094140671">"Bacı"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Həyat yoldaşı"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"Fərdi"</string>
- <string name="sipAddressTypeHome" msgid="5918441930656878367">"Ev"</string>
+ <string name="sipAddressTypeHome" msgid="5918441930656878367">"Əsas səhifə"</string>
<string name="sipAddressTypeWork" msgid="7873967986701216770">"İş"</string>
<string name="sipAddressTypeOther" msgid="6317012577345187275">"Digər"</string>
<string name="quick_contacts_not_available" msgid="1262709196045052223">"Bu kontakta baxmaq üçün heç bir tətbiq tapılmadı."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 70a191e29ff1..454a21e1f719 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -98,9 +98,9 @@
<string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi-тэлефанія"</string>
<string name="notification_channel_sim" msgid="5098802350325677490">"Статус SIM-карты"</string>
<string name="notification_channel_sim_high_prio" msgid="642361929452850928">"Стан SIM-карты з высокім прыярытэтам"</string>
- <string name="peerTtyModeFull" msgid="337553730440832160">"Аднарангавая прылада запытала рэжым поўнафункцыянальнага TTY"</string>
- <string name="peerTtyModeHco" msgid="5626377160840915617">"Аднарангавая прылада запытала рэжым TTY з магчымасцю чуць суразмоўніка"</string>
- <string name="peerTtyModeVco" msgid="572208600818270944">"Аднарангавая прылада запытала рэжым TTY з магчымасцю чуць суразмоўніка"</string>
+ <string name="peerTtyModeFull" msgid="337553730440832160">"Аднарангавая прылада запытала рэжым TTY FULL"</string>
+ <string name="peerTtyModeHco" msgid="5626377160840915617">"Аднарангавая прылада запытала рэжым TTY НСО"</string>
+ <string name="peerTtyModeVco" msgid="572208600818270944">"Аднарангавая прылада запытала рэжым TTY VCO"</string>
<string name="peerTtyModeOff" msgid="2420380956369226583">"Аднарангавая прылада запытала рэжым TTY OFF"</string>
<string name="serviceClassVoice" msgid="2065556932043454987">"Голас"</string>
<string name="serviceClassData" msgid="4148080018967300248">"Дадзеныя"</string>
@@ -703,10 +703,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>
@@ -756,14 +756,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>
@@ -786,19 +786,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>
@@ -953,7 +953,7 @@
<string name="permlab_addVoicemail" msgid="4770245808840814471">"дадаць галасавое паведамленне"</string>
<string name="permdesc_addVoicemail" msgid="5470312139820074324">"Дазваляе прыкладанням дадаваць паведамленні ў вашу скрыню галасавой пошты."</string>
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"змяніць дазволы геапазіцыянавання для браўзэра"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"Дазваляе праграме змяняць дазволы геалакацыі браўзера. Шкодныя праграмы могуць выкарыстоўваць гэта, каб адпраўляць даныя аб месцазнаходжанні на любыя вэб-сайты."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"Дазваляе прыкладанням змяняць дазволы геалакацыі браўзэра. Шкоднасныя прыкладанні могуць выкарыстоўваць гэта, каб дазваляць адпраўку інфармацыі аб месцазнаходжанні выпадковым вэб-сайтам."</string>
<string name="save_password_message" msgid="2146409467245462965">"Вы хочаце, каб браўзэр запомніў гэты пароль?"</string>
<string name="save_password_notnow" msgid="2878327088951240061">"Не зараз"</string>
<string name="save_password_remember" msgid="6490888932657708341">"Запомніць"</string>
@@ -1351,8 +1351,8 @@
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Рэжым USB-мадэма"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI праз USB"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-прылада падключана"</string>
- <string name="usb_notification_message" msgid="4715163067192110676">"Дакраніцеся, каб убачыць іншыя параметры."</string>
- <string name="usb_power_notification_message" msgid="7284765627437897702">"Падключаная прылада зараджаецца. Дакраніцеся, каб убачыць іншыя параметры."</string>
+ <string name="usb_notification_message" msgid="4715163067192110676">"Дакраніцеся, каб атрымаць іншыя параметры."</string>
+ <string name="usb_power_notification_message" msgid="7284765627437897702">"Зарадка падключанай прылады. Націсніце, каб убачыць іншыя параметры."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Выяўлены аксесуар аналагавага аўдыя"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Далучаная прылада не сумяшчальная з гэтым тэлефонам. Націсніце, каб даведацца больш."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Адладка па USB падключана"</string>
@@ -1539,7 +1539,7 @@
<string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"Не атрымалася запусціць <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="shareactionprovider_share_with" msgid="2753089758467748982">"Апублікаваць з дапамогай"</string>
<string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Адправiць з дапамогай прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="content_description_sliding_handle" msgid="982510275422590757">"Маркер для перасоўвання. Дакраніцеся і ўтрымлівайце."</string>
+ <string name="content_description_sliding_handle" msgid="982510275422590757">"Ручка для перасоўвання. Націсніце і ўтрымлівайце."</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"Прагартайце, каб разблакаваць."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"Перайсці да пачатковай старонкі"</string>
<string name="action_bar_up_description" msgid="6611579697195026932">"Перайсці ўверх"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 413feb322fa1..fd53b69a61a1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -575,7 +575,7 @@
<string name="face_acquired_not_detected" msgid="2945945257956443257">"Postavite lice direktno ispred telefona"</string>
<string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Previše pokreta. Držite telefon mirno."</string>
<string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ponovo registrirajte lice."</string>
- <string name="face_acquired_too_different" msgid="4699657338753282542">"Više nije moguće prepoznati lice. Pokušajte opet."</string>
+ <string name="face_acquired_too_different" msgid="4699657338753282542">"Nije više moguće prepoznati lice. Pokušajte opet."</string>
<string name="face_acquired_too_similar" msgid="7684650785108399370">"Previše slično, promijenite položaj."</string>
<string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Malo manje zakrenite glavu."</string>
<string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Malo manje zakrenite glavu."</string>
@@ -956,7 +956,7 @@
<string name="save_password_remember" msgid="6490888932657708341">"Zapamti"</string>
<string name="save_password_never" msgid="6776808375903410659">"Nikad"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"Nemate odobrenje za otvaranje ove stranice."</string>
- <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međumemoriju."</string>
+ <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međuspremnik."</string>
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="more_item_label" msgid="7419249600215749115">"Više"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index df42b35f76b8..fdb8f4584b95 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -974,8 +974,8 @@
<string name="searchview_description_submit" msgid="6771060386117334686">"Envia la consulta"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"Cerca per veu"</string>
<string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Vols activar l\'exploració tàctil?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interaccionar amb la tauleta."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració per tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interaccionar amb el telèfon."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interactuar amb la tauleta."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració per tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interactuar amb el telèfon."</string>
<string name="oneMonthDurationPast" msgid="4538030857114635777">"Fa 1 mes"</string>
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Fa més d\'1 mes"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1229,7 +1229,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"S\'ha establert el so de silenci"</string>
<string name="volume_call" msgid="7625321655265747433">"Volum en trucada"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Volum en trucada per Bluetooth"</string>
- <string name="volume_alarm" msgid="4486241060751798448">"Volum d\'alarma"</string>
+ <string name="volume_alarm" msgid="4486241060751798448">"Volum de l\'alarma"</string>
<string name="volume_notification" msgid="6864412249031660057">"Volum de notificacions"</string>
<string name="volume_unknown" msgid="4041914008166576293">"Volum"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"Volum del Bluetooth"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 9e35f28f9133..4ff597577be6 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1126,8 +1126,8 @@
<string name="loading" msgid="3138021523725055037">"Loading…"</string>
<string name="capital_on" msgid="2770685323900821829">"ON"</string>
<string name="capital_off" msgid="7443704171014626777">"OFF"</string>
- <string name="checked" msgid="9179896827054513119">"checked"</string>
- <string name="not_checked" msgid="7972320087569023342">"not checked"</string>
+ <string name="checked" msgid="9179896827054513119">"ticked"</string>
+ <string name="not_checked" msgid="7972320087569023342">"not ticked"</string>
<string name="whichApplication" msgid="5432266899591255759">"Complete action using"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Complete action using %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Complete action"</string>
@@ -1992,7 +1992,7 @@
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> spreadsheet"</string>
<string name="mime_type_presentation" msgid="1145384236788242075">"Presentation"</string>
<string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> presentation"</string>
- <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on in Airplane mode"</string>
+ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth will stay on during aeroplane mode"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Loading"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3ecfd911eaa2..5db4f42a9a22 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -315,7 +315,7 @@
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Realizar gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string>
- <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de huella digital"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de huellas digitales"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index cdb3e3b9e700..5ee67d95a418 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -292,7 +292,7 @@
<string name="permgrouplab_sms" msgid="795737735126084874">"Tekstiviestit"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"lähettää ja tarkastella tekstiviestejä"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"Tiedostot ja media"</string>
- <string name="permgroupdesc_storage" msgid="6351503740613026600">"käyttää laitteellesi tallennettuja kuvia, mediatiedostoja ja muita tiedostoja"</string>
+ <string name="permgroupdesc_storage" msgid="6351503740613026600">"käyttää laitteellesi tallennettuja valokuvia, mediatiedostoja ja muita tiedostoja"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"tallentaa ääntä"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Liikkuminen"</string>
@@ -1886,7 +1886,7 @@
<string name="app_category_game" msgid="4534216074910244790">"Pelit"</string>
<string name="app_category_audio" msgid="8296029904794676222">"Musiikki ja audio"</string>
<string name="app_category_video" msgid="2590183854839565814">"Elokuvat ja videot"</string>
- <string name="app_category_image" msgid="7307840291864213007">"Kuvat ja kuvat"</string>
+ <string name="app_category_image" msgid="7307840291864213007">"Kuvat ja valokuvat"</string>
<string name="app_category_social" msgid="2278269325488344054">"Some ja viestintä"</string>
<string name="app_category_news" msgid="1172762719574964544">"Uutiset ja lehdet"</string>
<string name="app_category_maps" msgid="6395725487922533156">"Kartat ja navigointi"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5f84c120acd7..9d2e267472e3 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -315,7 +315,7 @@
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Contrôle le niveau de zoom et le positionnement de l\'écran."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Effectuer des gestes"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string>
- <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes d\'empreinte digitale"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes avec l\'empreinte digitale"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 3256be60b29c..0170f1659b30 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -835,7 +835,7 @@
<string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pausar"</string>
<string name="lockscreen_transport_play_description" msgid="106868788691652733">"Reproducir"</string>
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Deter"</string>
- <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Retroceder"</string>
+ <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Rebobinar"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Avance rápido"</string>
<string name="emergency_calls_only" msgid="3057351206678279851">"Só chamadas de emerxencia"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Bloqueada pola rede"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index fa5284f79d5c..8b0b37448dec 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1146,7 +1146,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>
@@ -1232,7 +1232,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"સાઇલેન્ટ રિંગટોન સેટ કરી"</string>
<string name="volume_call" msgid="7625321655265747433">"ઇન-કૉલ વૉલ્યૂમ"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"બ્લૂટૂથ ઇન-કૉલ વૉલ્યૂમ"</string>
- <string name="volume_alarm" msgid="4486241060751798448">"અલાર્મ વૉલ્યૂમ"</string>
+ <string name="volume_alarm" msgid="4486241060751798448">"એલાર્મ વૉલ્યૂમ"</string>
<string name="volume_notification" msgid="6864412249031660057">"સૂચના વૉલ્યૂમ"</string>
<string name="volume_unknown" msgid="4041914008166576293">"વૉલ્યૂમ"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"બ્લૂટૂથ વૉલ્યૂમ"</string>
@@ -1513,7 +1513,7 @@
<string name="storage_usb_drive" msgid="448030813201444573">"USB ડ્રાઇવ"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ડ્રાઇવ"</string>
<string name="storage_usb" msgid="2391213347883616886">"USB સ્ટોરેજ"</string>
- <string name="extract_edit_menu_button" msgid="63954536535863040">"ફેરફાર કરો"</string>
+ <string name="extract_edit_menu_button" msgid="63954536535863040">"સંપાદિત કરો"</string>
<string name="data_usage_warning_title" msgid="9034893717078325845">"ડેટા ચેતવણી"</string>
<string name="data_usage_warning_body" msgid="1669325367188029454">"તમે <xliff:g id="APP">%s</xliff:g> ડેટા વાપર્યો છે"</string>
<string name="data_usage_mobile_limit_title" msgid="3911447354393775241">"મોબાઇલ ડેટાની મર્યાદા આવી ગઈ"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 5498f81a0dee..bb1ad3230fe7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -297,7 +297,7 @@
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"hanganyag rögzítése"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Testmozgás"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"hozzáférés a testmozgási adatokhoz"</string>
- <string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
+ <string name="permgrouplab_camera" msgid="9090413408963547706">"Fényképezőgép"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotók és videók készítése"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Hívásnaplók"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"hívásnapló olvasása és írása"</string>
@@ -1872,8 +1872,8 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"A feloldáshoz koppintson rá"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Csatlakoztatva a(z) <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> eszközhöz"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Koppintson ide a fájlok megtekintéséhez"</string>
- <string name="pin_target" msgid="8036028973110156895">"Kitűzés"</string>
- <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> kitűzése"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Rögzítés"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítése"</string>
<string name="unpin_target" msgid="3963318576590204447">"Feloldás"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítésének feloldása"</string>
<string name="app_info" msgid="6113278084877079851">"Alkalmazásinformáció"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 4c9a720cd8ce..aabfc80fe8fa 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -48,7 +48,7 @@
<string name="invalidPin" msgid="7542498253319440408">"Մուտքագրեք PIN, որը 4-ից 8 թիվ է:"</string>
<string name="invalidPuk" msgid="8831151490931907083">"Մուտքագրեք PUK, որն 8 կամ ավել թիվ ունի:"</string>
<string name="needPuk" msgid="7321876090152422918">"Ձեր SIM քարտը PUK-ով կողպված է: Մուտքագրեք PUK կոդը այն ապակողպելու համար:"</string>
- <string name="needPuk2" msgid="7032612093451537186">"Մուտքագրեք PUK2-ը՝ SIM քարտն արգելահանելու համար:"</string>
+ <string name="needPuk2" msgid="7032612093451537186">"Մուտքագրեք PUK2-ը` SIM քարտն արգելահանելու համար:"</string>
<string name="enablePin" msgid="2543771964137091212">"Ձախողվեց: Միացրեք SIM/RUIM կողպումը:"</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
<item quantity="one">Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն արգելափակվելու է:</item>
@@ -399,7 +399,7 @@
<string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Թույլ է տալիս հավելվածին փոփոխել ձեր պլանշետի զանգերի մատյանը, այդ թվում` մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել` ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:"</string>
<string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Թույլ է տալիս հավելվածին փոփոխել Android TV սարքի զանգերի մատյանը, այդ թվում՝ մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել՝ ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:"</string>
<string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Թույլ է տալիս հավելվածին փոփոխել ձեր հեռախոսի զանգերի մատյանը, այդ թվում` մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել` ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:"</string>
- <string name="permlab_bodySensors" msgid="3411035315357380862">"օգտագործել մարմնի սենսորները (օրինակ՝ սրտի կծկումների հաճախականության չափիչ)"</string>
+ <string name="permlab_bodySensors" msgid="3411035315357380862">"օգտագործել մարմնի սենսորները (օրինակ` սրտի կծկումների հաճախականության չափիչ)"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"Հավելվածին թույլ է տալիս մուտք ունենալ սենսորների տվյալներին, որոնք վերահսկում են ձեր ֆիզիկական վիճակը, օրինակ՝ ձեր սրտի զարկերը:"</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"Կարդալ օրացույցի միջոցառումները և տվյալները"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Այս հավելվածը կարող է կարդալ օրացույցի՝ ձեր պլանշետում պահված բոլոր միջոցառումները, ինչպես նաև հրապարակել կամ պահել ձեր օրացույցի տվյալները:"</string>
@@ -418,7 +418,7 @@
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"տեղադրության մասին տվյալների հասանելիություն ֆոնային ռեժիմում"</string>
<string name="permdesc_accessBackgroundLocation" msgid="623676842127558197">"Այս հավելվածը ինչպես ակտիվ, այնպես էլ ֆոնային ռեժիմում աշխատելիս կարող է տեսնել տեղադրության տվյալները։"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"փոխել ձեր աուդիո կարգավորումները"</string>
- <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ՝ ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:"</string>
+ <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ` ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:"</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ձայնագրել աուդիո ֆայլ"</string>
<string name="permdesc_recordAudio" msgid="3976213377904701093">"Այս հավելվածը ցանկացած պահի կարող է ձայնագրել խոսափողի օգնությամբ:"</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"ուղարկել հրամաններ SIM քարտին"</string>
@@ -477,7 +477,7 @@
<string name="permlab_changeTetherState" msgid="9079611809931863861">"փոխել միացված կապը"</string>
<string name="permdesc_changeTetherState" msgid="3025129606422533085">"Թույլ է տալիս հավելվածին փոխել կապված ցանցի միացման կարգավիճակը:"</string>
<string name="permlab_accessWifiState" msgid="5552488500317911052">"դիտել Wi-Fi կապերը"</string>
- <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Թույլ է տալիս հավելվածին տեսնել Wi-Fi ցանցի տեղեկություններ, ինչպես օրինակ՝ արդյոք Wi-Fi-ը միացված է, թե` ոչ, և միացված Wi-Fi սարքի անունը:"</string>
+ <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Թույլ է տալիս հավելվածին տեսնել Wi-Fi ցանցի տեղեկություններ, ինչպես օրինակ` արդյոք Wi-Fi-ը միացված է, թե` ոչ, և միացված Wi-Fi սարքի անունը:"</string>
<string name="permlab_changeWifiState" msgid="7947824109713181554">"միանալ Wi-Fi-ին և անջատվել դրանից"</string>
<string name="permdesc_changeWifiState" msgid="7170350070554505384">"Թույլ է տալիս հավելվածին միանալ Wi-Fi մուտքի կետերին և անջատվել այդ կետերից, ինչպես նաև կատարել սարքի կարգավորման փոփոխություններ Wi-Fi ցանցերի համար:"</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"թույլատրել Բազմասփյուռ Wi-Fi-ի ընդունումը"</string>
@@ -598,7 +598,7 @@
</string-array>
<string name="face_icon_content_description" msgid="465030547475916280">"Դեմքի պատկերակ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"կարդալ համաժամացման կարգավորումները"</string>
- <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ՝ այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string>
+ <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ` այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"համաժամացումը փոխարկել միացվածի և անջատվածի"</string>
<string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Թույլ է տալիս հավելվածին փոփոխել համաժամացման կարգավորումները հաշվի համար: Օրինակ, այն կարող է օգտագործվել` միացնելու Մարդիկ հավելվածի համաժամացումը հաշվի հետ:"</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"կարդալ համաժամացման վիճակագրությունը"</string>
@@ -859,7 +859,7 @@
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Մոռացե՞լ եք սխեման:"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Հաշվի ապակողպում"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Չափից շատ սխեմայի փորձեր"</string>
- <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Ապակողպելու համար՝ մուտք գործեք ձեր Google հաշվով:"</string>
+ <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Ապակողպելու համար` մուտք գործեք ձեր Google հաշվով:"</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Օգտանուն (էլփոստ)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Գաղտնաբառ"</string>
<string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Մուտք գործել"</string>
@@ -1404,7 +1404,7 @@
<string name="ime_action_done" msgid="6299921014822891569">"Պատրաստ է"</string>
<string name="ime_action_previous" msgid="6548799326860401611">"Նախորդ"</string>
<string name="ime_action_default" msgid="8265027027659800121">"Կատարել"</string>
- <string name="dial_number_using" msgid="6060769078933953531">"Հավաքել հեռախոսահամարը՝\nօգտագործելով <xliff:g id="NUMBER">%s</xliff:g>-ը"</string>
+ <string name="dial_number_using" msgid="6060769078933953531">"Հավաքել հեռախոսահամարը`\nօգտագործելով <xliff:g id="NUMBER">%s</xliff:g>-ը"</string>
<string name="create_contact_using" msgid="6200708808003692594">"Ստեղծել կոնտակտ`\nօգտագործելով <xliff:g id="NUMBER">%s</xliff:g>-ը"</string>
<string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Հետևյալ մեկ կամ ավել հավելվածներ մուտքի թույլտվության հարցում են անում` այժմ և հետագայում ձեր հաշվին մուտք ունենալու համար:"</string>
<string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Ցանկանու՞մ եք թույլատրել այս հարցումը:"</string>
@@ -1471,7 +1471,7 @@
<string name="number_picker_increment_button" msgid="7621013714795186298">"Ավելացնել"</string>
<string name="number_picker_decrement_button" msgid="5116948444762708204">"Նվազեցնել"</string>
<string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> հպեք և պահեք:"</string>
- <string name="number_picker_increment_scroll_action" msgid="8310191318914268271">"Սահեցրեք վերև՝ ավելացնելու համար, և ներքև՝ նվազեցնելու համար:"</string>
+ <string name="number_picker_increment_scroll_action" msgid="8310191318914268271">"Սահեցրեք վերև` ավելացնելու համար, և ներքև` նվազեցնելու համար:"</string>
<string name="time_picker_increment_minute_button" msgid="7195870222945784300">"Աճեցնել րոպեն"</string>
<string name="time_picker_decrement_minute_button" msgid="230925389943411490">"Նվազեցնել րոպեն"</string>
<string name="time_picker_increment_hour_button" msgid="3063572723197178242">"Աճեցնել ժամը"</string>
@@ -1597,7 +1597,7 @@
<string name="kg_invalid_puk" msgid="4809502818518963344">"Վերամուտքագրեք ճիշտ PUK ծածկագիրը: Կրկնվող փորձերը ընդմիշտ կկասեցնեն SIM քարտը:"</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN ծածկագրերը չեն համընկնում"</string>
<string name="kg_login_too_many_attempts" msgid="699292728290654121">"Չափից շատ սխեմայի փորձեր"</string>
- <string name="kg_login_instructions" msgid="3619844310339066827">"Ապակողպելու համար՝ մուտք գործեք ձեր Google հաշվով:"</string>
+ <string name="kg_login_instructions" msgid="3619844310339066827">"Ապակողպելու համար` մուտք գործեք ձեր Google հաշվով:"</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"Օգտանուն (էլփոստ)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"Գաղտնաբառը"</string>
<string name="kg_login_submit_button" msgid="893611277617096870">"Մուտք գործել"</string>
@@ -1951,7 +1951,7 @@
<string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածների ստորագրությունները տարբեր են"</string>
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Չհաջողվեց վերականգնել դյուրանցումը"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Դյուրանցումն անջատված է"</string>
- <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ԱՊԱՏԵՂԱԴՐԵԼ"</string>
+ <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ՀԵՌԱՑՆԵԼ"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"ԲԱՑԵԼ"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Հայտնաբերվել է վնասաբեր հավելված"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c90267ed5a59..7963ba7f67a9 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1239,7 +1239,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-km/strings.xml b/core/res/res/values-km/strings.xml
index 7d627cce5e1b..50e2e1541ec8 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1974,7 +1974,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-mk/strings.xml b/core/res/res/values-mk/strings.xml
index ae8a7206f23f..a80779cfaca5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -971,7 +971,7 @@
<string name="searchview_description_search" msgid="1045552007537359343">"Пребарај"</string>
<string name="searchview_description_query" msgid="7430242366971716338">"Пребарај барање"</string>
<string name="searchview_description_clear" msgid="1989371719192982900">"Исчисти барање"</string>
- <string name="searchview_description_submit" msgid="6771060386117334686">"Испрати барање"</string>
+ <string name="searchview_description_submit" msgid="6771060386117334686">"Поднеси барање"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"Гласовно пребарување"</string>
<string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Овозможи „Истражувај со допир“?"</string>
<string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> сака да овозможи „Истражувај со допир“. Кога е вклучено „Истражувај со допир“, може да се слушнат или да се видат описи на она што е под вашиот прст или да се прават движења за комуницирање со таблетот."</string>
@@ -1436,7 +1436,7 @@
<string name="upload_file" msgid="8651942222301634271">"Избери датотека"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"Не е избрана датотека"</string>
<string name="reset" msgid="3865826612628171429">"Ресетирај"</string>
- <string name="submit" msgid="862795280643405865">"Испрати"</string>
+ <string name="submit" msgid="862795280643405865">"Поднеси"</string>
<string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Апликацијата за возење работи"</string>
<string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Допрете за да излезете од апликацијата за возење."</string>
<string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 376d6b75b291..7145ef3da91a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1077,7 +1077,7 @@
<string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll" msgid="1532369154488982046">"Merk alt"</string>
<string name="cut" msgid="2561199725874745819">"Klipp ut"</string>
- <string name="copy" msgid="5472512047143665218">"Kopiér"</string>
+ <string name="copy" msgid="5472512047143665218">"Kopier"</string>
<string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"Kunne ikke kopiere til utklippstavlen"</string>
<string name="paste" msgid="461843306215520225">"Lim inn"</string>
<string name="paste_as_plain_text" msgid="7664800665823182587">"Lim inn som ren tekst"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 9a419a83197f..b5194eb7ba1b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -882,7 +882,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-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c509dc177a1c..244d0e680d18 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1321,7 +1321,7 @@
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Отмена"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Запомнить выбор"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"Это можно изменить позже в разделе настроек \"Приложения\"."</string>
- <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Разрешать всегда"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Всегда разрешать"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Не разрешать"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"SIM-карта удалена"</string>
<string name="sim_removed_message" msgid="9051174064474904617">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index afc742d64c23..88b62f439ba2 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1802,7 +1802,7 @@
<item quantity="other">I %d tim</item>
<item quantity="one">I en 1 tim</item>
</plurals>
- <string name="zen_mode_until" msgid="2250286190237669079">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_until" msgid="2250286190237669079">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="7046911727540499275">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nästa alarm)"</string>
<string name="zen_mode_forever" msgid="740585666364912448">"Tills du stänger av"</string>
<string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Tills du inaktiverar Stör ej"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 77c4042d9f00..e94856bb1f53 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -293,7 +293,7 @@
<string name="permgroupdesc_sms" msgid="5726462398070064542">"itume na iangalie SMS"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"Faili na maudhui"</string>
<string name="permgroupdesc_storage" msgid="6351503740613026600">"ifikie picha, maudhui na faili kwenye kifaa chako"</string>
- <string name="permgrouplab_microphone" msgid="2480597427667420076">"Maikrofoni"</string>
+ <string name="permgrouplab_microphone" msgid="2480597427667420076">"Kipokea sauti"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"irekodi sauti"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Shughuli za kimwili"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ifikie shughuli zako za kimwili"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 33dd373b3fe4..37bb5cd12789 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1116,7 +1116,7 @@
<string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll" msgid="1532369154488982046">"Вибрати все"</string>
- <string name="cut" msgid="2561199725874745819">"Вирізати"</string>
+ <string name="cut" msgid="2561199725874745819">"Виріз."</string>
<string name="copy" msgid="5472512047143665218">"Копіювати"</string>
<string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"Не вдалося скопіювати в буфер обміну"</string>
<string name="paste" msgid="461843306215520225">"Вставити"</string>
@@ -1829,7 +1829,7 @@
<item quantity="other">Протягом %1$d хв (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
- <item quantity="one">%1$d година (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">%1$d годину (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="few">%1$d години (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="many">%1$d годин (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">%1$d години (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 42a658e50073..a896a65eab08 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4175,6 +4175,35 @@
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
<integer name="config_defaultRefreshRateInZone">0</integer>
+ <!-- The display uses different gamma curves for different refresh rates. It's hard for panel
+ vendor to tune the curves to have exact same brightness for different refresh rate. So
+ flicker could be observed at switch time. The issue can be observed on the screen with
+ even full white content at the high brightness. To prevent flickering, we support fixed
+ refresh rates if the display and ambient brightness are equal to or above the provided
+ thresholds. You can define multiple threshold levels as higher brightness environments
+ may have lower display brightness requirements for the flickering is visible. And the
+ high brightness environment could have higher threshold.
+ For example, fixed refresh rate if
+ display brightness >= disp0 && ambient brightness >= amb0
+ || display brightness >= disp1 && ambient brightness >= amb1 -->
+ <integer-array translatable="false" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate">
+ <!--
+ <item>disp0</item>
+ <item>disp1</item>
+ -->
+ </integer-array>
+
+ <integer-array translatable="false" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate">
+ <!--
+ <item>amb0</item>
+ <item>amb1</item>
+ -->
+ </integer-array>
+
+ <!-- Default refresh rate in the high zone defined by brightness and ambient thresholds.
+ If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
+ <integer name="config_fixedRefreshRateInHighZone">0</integer>
+
<!-- The type of the light sensor to be used by the display framework for things like
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
<string name="config_displayLightSensorType" translatable="false" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c505afe0509e..4c255f13ec18 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3790,6 +3790,11 @@
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
+ <!-- For fixed refresh rate displays in high brightness-->
+ <java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
+ <java-symbol type="array" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate" />
+ <java-symbol type="array" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate" />
+
<!-- For Auto-Brightness -->
<java-symbol type="string" name="config_displayLightSensorType" />
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index b39c89b62eb1..6aa5dfc5a11e 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -129,6 +129,7 @@
<!-- virtual display test permissions -->
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
+ <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" />
<!-- color extraction test permissions -->
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
index daf613976358..0f6284d22d10 100644
--- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
+++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
@@ -247,6 +247,25 @@ public class VirtualDisplayTest extends AndroidTestCase {
assertDisplayUnregistered(display);
}
+ /**
+ * Ensures that an application can create a trusted virtual display with the permission
+ * {@code ADD_TRUSTED_DISPLAY}.
+ */
+ public void testTrustedVirtualDisplay() throws Exception {
+ VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
+ WIDTH, HEIGHT, DENSITY, mSurface,
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED);
+ assertNotNull("virtual display must not be null", virtualDisplay);
+
+ Display display = virtualDisplay.getDisplay();
+ try {
+ assertDisplayRegistered(display, Display.FLAG_PRIVATE | Display.FLAG_TRUSTED);
+ } finally {
+ virtualDisplay.release();
+ }
+ assertDisplayUnregistered(display);
+ }
+
private void assertDisplayRegistered(Display display, int flags) {
assertNotNull("display object must not be null", display);
assertTrue("display must be valid", display.isValid());
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index e5492714b29f..3c990abaec87 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -163,3 +163,10 @@ prebuilt_etc {
src: "com.android.car.ui.paintbooth.xml",
filename_from_src: true,
}
+
+prebuilt_etc {
+ name: "allowed_privapp_com.android.carshell",
+ sub_dir: "permissions",
+ src: "com.android.car.shell.xml",
+ filename_from_src: true,
+}
diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml
new file mode 100644
index 000000000000..32666c8d9f68
--- /dev/null
+++ b/data/etc/car/com.android.car.shell.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.shell">
+ <permission name="android.permission.INSTALL_PACKAGES" />
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 7292e0796bf5..f21e9bff16ec 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -43,5 +43,8 @@
<!-- use for CarServiceTest -->
<permission name="android.permission.SET_ACTIVITY_WATCHER"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+ <!-- use for rotary fragment to enable/disable packages related to rotary -->
+ <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index fe1182ecad4f..e473c55ce010 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -56,5 +56,7 @@
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
<permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
<permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/>
+ <permission name="android.permission.READ_DREAM_STATE"/>
+ <permission name="android.permission.READ_DREAM_SUPPRESSION"/>
</privapp-permissions>
</permissions>
diff --git a/diff b/diff
deleted file mode 100644
index 5c75d88e6789..000000000000
--- a/diff
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
-index fc43882..832dc91 100644
---- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
-+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
-@@ -67,6 +67,7 @@ import java.util.Arrays;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
-+import java.util.NoSuchElementException;
-
- /**
- * This class represents an accessibility client - either an AccessibilityService or a UiAutomation.
-@@ -978,7 +979,11 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
- /* ignore */
- }
- if (mService != null) {
-- mService.unlinkToDeath(this, 0);
-+ try {
-+ mService.unlinkToDeath(this, 0);
-+ }catch(NoSuchElementException e) {
-+ Slog.e(LOG_TAG, "Failed unregistering death link");
-+ }
- mService = null;
- }
-
diff --git a/drm/jni/Android.bp b/drm/jni/Android.bp
index 1e33f0ea5094..68757d86fb89 100644
--- a/drm/jni/Android.bp
+++ b/drm/jni/Android.bp
@@ -21,6 +21,7 @@ cc_library_shared {
shared_libs: [
"libdrmframework",
+ "libdrmframeworkcommon",
"liblog",
"libutils",
"libandroid_runtime",
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index bc1301a86455..fe5c1be05927 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -327,7 +327,7 @@ public class Typeface {
* 1) Create Typeface from ttf file.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
+ * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf");
* Typeface typeface = builder.build();
* </code>
* </pre>
@@ -335,7 +335,7 @@ public class Typeface {
* 2) Create Typeface from ttc file in assets directory.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc");
+ * Typeface.Builder builder = new Typeface.Builder(getAssets(), "your_font_file.ttc");
* builder.setTtcIndex(2); // Set index of font collection.
* Typeface typeface = builder.build();
* </code>
@@ -344,7 +344,7 @@ public class Typeface {
* 3) Create Typeface with variation settings.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
+ * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf");
* builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
* builder.setWeight(700); // Tell the system that this is a bold font.
* builder.setItalic(true); // Tell the system that this is an italic style font.
diff --git a/packages/CarSystemUI/res/layout/headsup_container_bottom.xml b/packages/CarSystemUI/res/layout/headsup_container_bottom.xml
index 5aab0a172b99..f43f02dfcc8c 100644
--- a/packages/CarSystemUI/res/layout/headsup_container_bottom.xml
+++ b/packages/CarSystemUI/res/layout/headsup_container_bottom.xml
@@ -45,14 +45,13 @@
app:layout_constraintBottom_toBottomOf="@+id/gradient_edge"
app:layout_constraintTop_toTopOf="parent"/>
- <FrameLayout
+ <com.android.car.notification.headsup.HeadsUpContainerView
android:id="@+id/headsup_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/headsup_notification_top_margin"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- />
+ app:layout_constraintBottom_toBottomOf="parent"/>
-</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/CarSystemUI/res/values-af/strings.xml b/packages/CarSystemUI/res/values-af/strings.xml
deleted file mode 100644
index 2ab3aa44a86c..000000000000
--- a/packages/CarSystemUI/res/values-af/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Stemherkenning nou deur gekoppelde Bluetooth-toestel hanteer"</string>
- <string name="car_guest" msgid="318393171202663722">"Gas"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gas"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Voeg gebruiker by"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nuwe gebruiker"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Enige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Laai tans"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Laai tans gebruiker (van <xliff:g id="FROM_USER">%1$d</xliff:g> na <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-am/strings.xml b/packages/CarSystemUI/res/values-am/strings.xml
deleted file mode 100644
index d5b580e3dd9d..000000000000
--- a/packages/CarSystemUI/res/values-am/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ዝቅተኛ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ከፍተኛ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"የድምፅ ለይቶ ማወቅ አሁን በተገናኘ የብሉቱዝ መሣሪያ ይስተናገዳል"</string>
- <string name="car_guest" msgid="318393171202663722">"እንግዳ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"እንግዳ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ተጠቃሚ አክል"</string>
- <string name="car_new_user" msgid="6637442369728092473">"አዲስ ተጠቃሚ"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሳቸውን ቦታ ማቀናበር አለባቸው።"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ማዘመን ይችላል።"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"በመጫን ላይ"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ተጠቃሚን (ከ<xliff:g id="FROM_USER">%1$d</xliff:g> ወደ <xliff:g id="TO_USER">%2$d</xliff:g>) በመጫን ላይ"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ar/strings.xml b/packages/CarSystemUI/res/values-ar/strings.xml
deleted file mode 100644
index 09b302d85eab..000000000000
--- a/packages/CarSystemUI/res/values-ar/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"حد أدنى"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"حد أقصى"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"تتم معالجة التعرّف على الصوت الآن من خلال جهاز بلوتوث متصل."</string>
- <string name="car_guest" msgid="318393171202663722">"ضيف"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ضيف"</string>
- <string name="car_add_user" msgid="4067337059622483269">"إضافة مستخدم"</string>
- <string name="car_new_user" msgid="6637442369728092473">"مستخدم جديد"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"عند إضافة مستخدم جديد، على هذا المستخدم إعداد مساحته."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"يمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"جارٍ التحميل"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"جارٍ تحميل الملف الشخصي الجديد للمستخدم (من <xliff:g id="FROM_USER">%1$d</xliff:g> إلى <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-as/strings.xml b/packages/CarSystemUI/res/values-as/strings.xml
deleted file mode 100644
index a8aa74d8c7a4..000000000000
--- a/packages/CarSystemUI/res/values-as/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"সর্বনিম্ন"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"সৰ্বাধিক"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"কণ্ঠস্বৰৰ চিনাক্তকৰণ এতিয়া সংযুক্ত ব্লুটুথ ডিভাইচে নিয়ন্ত্ৰণ কৰে"</string>
- <string name="car_guest" msgid="318393171202663722">"অতিথি"</string>
- <string name="start_guest_session" msgid="497784785761754874">"অতিথি"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ব্যৱহাৰকাৰী যোগ দিয়ক"</string>
- <string name="car_new_user" msgid="6637442369728092473">"নতুন ব্যৱহাৰকাৰী"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰীক যোগ কৰে, তেতিয়া তেওঁ নিজৰ ঠাই ছেট আপ কৰাটো প্ৰয়োজন হয়।"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"যিকোনো ব্যৱহাৰকাৰীয়ে অন্য ব্যৱহাৰকাৰীৰ বাবে এপ্‌সমূহ আপডে’ট কৰিব পাৰে।"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ল’ড হৈ আছে"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ব্যৱহাৰকাৰী ল’ড হৈ আছে (<xliff:g id="FROM_USER">%1$d</xliff:g>ৰ পৰা to <xliff:g id="TO_USER">%2$d</xliff:g>লৈ)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-az/strings.xml b/packages/CarSystemUI/res/values-az/strings.xml
deleted file mode 100644
index 97facc27be68..000000000000
--- a/packages/CarSystemUI/res/values-az/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Səs tanınması qoşulmuş Bluetooth cihazı ilə icra edilir"</string>
- <string name="car_guest" msgid="318393171202663722">"Qonaq"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Qonaq"</string>
- <string name="car_add_user" msgid="4067337059622483269">"İstifadəçi əlavə edin"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Yeni İstifadəçi"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yeni istifadəçi əlavə etdiyinizdə həmin şəxs öz yerini təyin etməlidir."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"İstənilən istifadəçi digər bütün istifadəçilər üçün tətbiqləri güncəlləyə bilər."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Yüklənir"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"İstifadəçi yüklənir (<xliff:g id="FROM_USER">%1$d</xliff:g>-<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml b/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index ec310be7a4d8..000000000000
--- a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Prepoznavanjem glasa sada upravlja povezani Bluetooth uređaj"</string>
- <string name="car_guest" msgid="318393171202663722">"Gost"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gost"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Dodaj korisnika"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Učitava se"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Profil korisnika se učitava (iz<xliff:g id="FROM_USER">%1$d</xliff:g> u <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-be/strings.xml b/packages/CarSystemUI/res/values-be/strings.xml
deleted file mode 100644
index 17fc58451464..000000000000
--- a/packages/CarSystemUI/res/values-be/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мін"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Распазнаванне голасу выконвае падключаная прылада Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Госць"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Госць"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Дадаць карыстальніка"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Новы карыстальнік"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Калі вы дадаяце новага карыстальніка, яму трэба наладзіць свой профіль."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Кожны карыстальнік прылады можа абнаўляць праграмы для ўсіх іншых карыстальнікаў."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Ідзе загрузка"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ідзе загрузка профілю карыстальніка (ад <xliff:g id="FROM_USER">%1$d</xliff:g> да <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-bg/strings.xml b/packages/CarSystemUI/res/values-bg/strings.xml
deleted file mode 100644
index ae2db2d08f25..000000000000
--- a/packages/CarSystemUI/res/values-bg/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Гл. разпознаване се обработва от свързаното у-во с Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Гост"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Гост"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Добавяне на потребител"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Нов потребител"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Когато добавите нов потребител, той трябва да настрои работната си област."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Всеки потребител може да актуализира приложенията за всички останали потребители."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Зарежда се"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Потребителят се зарежда (от <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-bn/strings.xml b/packages/CarSystemUI/res/values-bn/strings.xml
deleted file mode 100644
index 9a01fad952eb..000000000000
--- a/packages/CarSystemUI/res/values-bn/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"সর্বনিম্ন"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"সর্বাধিক"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"কানেক্ট করা ব্লুটুথ ডিভাইস এখন ভয়েস শনাক্তকরণ ম্যানেজ করছে"</string>
- <string name="car_guest" msgid="318393171202663722">"অতিথি"</string>
- <string name="start_guest_session" msgid="497784785761754874">"অতিথি"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ব্যবহারকারীকে যোগ করুন"</string>
- <string name="car_new_user" msgid="6637442369728092473">"নতুন ব্যবহারকারী"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"নতুন ব্যবহারকারী যোগ করলে, তার স্পেস তাকে সেট-আপ করে নিতে হবে।"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"যেকোনও ব্যবহারকারী বাকি সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন।"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"লোড হচ্ছে"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ব্যবহারকারীর প্রোফাইল লোড করা হচ্ছে (<xliff:g id="FROM_USER">%1$d</xliff:g> থেকে <xliff:g id="TO_USER">%2$d</xliff:g>-এ)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-bs/strings.xml b/packages/CarSystemUI/res/values-bs/strings.xml
deleted file mode 100644
index 5ef9aeba3436..000000000000
--- a/packages/CarSystemUI/res/values-bs/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Prepoznavanjem glasa sada upravlja povezani Bluetooth uređaj"</string>
- <string name="car_guest" msgid="318393171202663722">"Gost"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gost"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Dodaj korisnika"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Bilo koji korisnik može ažurirati aplikacije za sve druge korisnike."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od korisnika <xliff:g id="FROM_USER">%1$d</xliff:g> do korisnika <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ca/strings.xml b/packages/CarSystemUI/res/values-ca/strings.xml
deleted file mode 100644
index 375fc5c10baf..000000000000
--- a/packages/CarSystemUI/res/values-ca/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Màx."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Reconeixement de veu gestionat per disp. Bluetooth connectat"</string>
- <string name="car_guest" msgid="318393171202663722">"Convidat"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Convidat"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Afegeix un usuari"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Usuari nou"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Quan s\'afegeix un usuari nou, aquesta persona ha de configurar el seu espai."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"S\'està carregant"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"S\'està carregant l\'usuari (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-cs/strings.xml b/packages/CarSystemUI/res/values-cs/strings.xml
deleted file mode 100644
index 8071cef72650..000000000000
--- a/packages/CarSystemUI/res/values-cs/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Rozpoznávání hlasu teď provádí připojené zařízení Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Host"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Host"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Přidat uživatele"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nový uživatel"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Každý nově přidaný uživatel si musí nastavit vlastní prostor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Každý uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Načítání"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Načítání uživatele (předchozí: <xliff:g id="FROM_USER">%1$d</xliff:g>, následující: <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-da/strings.xml b/packages/CarSystemUI/res/values-da/strings.xml
deleted file mode 100644
index b19cdcba5af9..000000000000
--- a/packages/CarSystemUI/res/values-da/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Talegenkendelse sker nu med den forbundne Blutetooth-enhed"</string>
- <string name="car_guest" msgid="318393171202663722">"Gæst"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gæst"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Tilføj bruger"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Ny bruger"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Når du tilføjer en ny bruger, skal vedkommende konfigurere sit område."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brugere kan opdatere apps for alle andre brugere."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Indlæser"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Indlæser bruger (fra <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-de/strings.xml b/packages/CarSystemUI/res/values-de/strings.xml
deleted file mode 100644
index 99ba13e4f3f8..000000000000
--- a/packages/CarSystemUI/res/values-de/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Spracherkennung jetzt über das verbundene Bluetooth-Gerät"</string>
- <string name="car_guest" msgid="318393171202663722">"Gast"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gast"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Nutzer hinzufügen"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Neuer Nutzer"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Jeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Wird geladen"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nutzer wird geladen (von <xliff:g id="FROM_USER">%1$d</xliff:g> bis <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-el/strings.xml b/packages/CarSystemUI/res/values-el/strings.xml
deleted file mode 100644
index e2d2cec34479..000000000000
--- a/packages/CarSystemUI/res/values-el/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Ελάχ."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Μεγ."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Φωνητική αναγνωση από συνδεδεμένη συσκευή Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Επισκέπτης"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Επισκέπτης"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Προσθήκη χρήστη"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Νέος χρήστης"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Οποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Φόρτωση"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Φόρτωση χρήστη (από <xliff:g id="FROM_USER">%1$d</xliff:g> έως <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-en-rAU/strings.xml b/packages/CarSystemUI/res/values-en-rAU/strings.xml
deleted file mode 100644
index b8bf9906916d..000000000000
--- a/packages/CarSystemUI/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Voice recognition now handled by connected Bluetooth device"</string>
- <string name="car_guest" msgid="318393171202663722">"Guest"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Guest"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Add user"</string>
- <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-en-rCA/strings.xml b/packages/CarSystemUI/res/values-en-rCA/strings.xml
deleted file mode 100644
index b8bf9906916d..000000000000
--- a/packages/CarSystemUI/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Voice recognition now handled by connected Bluetooth device"</string>
- <string name="car_guest" msgid="318393171202663722">"Guest"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Guest"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Add user"</string>
- <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-en-rGB/strings.xml b/packages/CarSystemUI/res/values-en-rGB/strings.xml
deleted file mode 100644
index b8bf9906916d..000000000000
--- a/packages/CarSystemUI/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Voice recognition now handled by connected Bluetooth device"</string>
- <string name="car_guest" msgid="318393171202663722">"Guest"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Guest"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Add user"</string>
- <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-en-rIN/strings.xml b/packages/CarSystemUI/res/values-en-rIN/strings.xml
deleted file mode 100644
index b8bf9906916d..000000000000
--- a/packages/CarSystemUI/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Voice recognition now handled by connected Bluetooth device"</string>
- <string name="car_guest" msgid="318393171202663722">"Guest"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Guest"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Add user"</string>
- <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-en-rXC/strings.xml b/packages/CarSystemUI/res/values-en-rXC/strings.xml
deleted file mode 100644
index 1ffa5ebde689..000000000000
--- a/packages/CarSystemUI/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎Min‎‏‎‎‏‎"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎Max‎‏‎‎‏‎"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎Voice recognition now handled by connected Bluetooth device‎‏‎‎‏‎"</string>
- <string name="car_guest" msgid="318393171202663722">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎Guest‎‏‎‎‏‎"</string>
- <string name="start_guest_session" msgid="497784785761754874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎Guest‎‏‎‎‏‎"</string>
- <string name="car_add_user" msgid="4067337059622483269">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎Add User‎‏‎‎‏‎"</string>
- <string name="car_new_user" msgid="6637442369728092473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎New User‎‏‎‎‏‎"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‎When you add a new user, that person needs to set up their space.‎‏‎‎‏‎"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎Any user can update apps for all other users.‎‏‎‎‏‎"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎Loading‎‏‎‎‏‎"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎Loading user (from ‎‏‎‎‏‏‎<xliff:g id="FROM_USER">%1$d</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎<xliff:g id="TO_USER">%2$d</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-es-rUS/strings.xml b/packages/CarSystemUI/res/values-es-rUS/strings.xml
deleted file mode 100644
index 027242a536fa..000000000000
--- a/packages/CarSystemUI/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Máx."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"El dispositivo Bluetooth administra el reconocimiento de voz"</string>
- <string name="car_guest" msgid="318393171202663722">"Invitado"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Invitado"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Agregar usuario"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Usuario nuevo"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cuando agregues un usuario nuevo, esa persona deberá configurar su espacio."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-es/strings.xml b/packages/CarSystemUI/res/values-es/strings.xml
deleted file mode 100644
index fe546051e729..000000000000
--- a/packages/CarSystemUI/res/values-es/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Máx."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"El dispositivo Bluetooth gestiona el reconocimiento de voz"</string>
- <string name="car_guest" msgid="318393171202663722">"Invitado"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Invitado"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Añadir usuario"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nuevo usuario"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cuando añades un usuario, esa persona debe configurar su espacio."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-et/strings.xml b/packages/CarSystemUI/res/values-et/strings.xml
deleted file mode 100644
index 2fa71a975973..000000000000
--- a/packages/CarSystemUI/res/values-et/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Häältuvastust haldab nüüd ühendatud Bluetoothi seade"</string>
- <string name="car_guest" msgid="318393171202663722">"Külaline"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Külaline"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Lisa kasutaja"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Uus kasutaja"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Iga kasutaja saab rakendusi värskendada kõigi teiste kasutajate jaoks."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Laadimine"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kasutaja laadimine (<xliff:g id="FROM_USER">%1$d</xliff:g> &gt; <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-eu/strings.xml b/packages/CarSystemUI/res/values-eu/strings.xml
deleted file mode 100644
index 36bcaae01443..000000000000
--- a/packages/CarSystemUI/res/values-eu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Konektatutako Bluetooth bidezko gailuak kudeatzen du ahotsa ezagutzeko eginbidea"</string>
- <string name="car_guest" msgid="318393171202663722">"Gonbidatua"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gonbidatua"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Gehitu erabiltzaile bat"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Erabiltzaile berria"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Erabiltzaile bat gehitzen duzunean, bere eremua konfiguratu beharko du."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Edozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Kargatzen"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Erabiltzailea kargatzen (<xliff:g id="FROM_USER">%1$d</xliff:g> izatetik<xliff:g id="TO_USER">%2$d</xliff:g> izatera igaroko da)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-fa/strings.xml b/packages/CarSystemUI/res/values-fa/strings.xml
deleted file mode 100644
index 3224899afb90..000000000000
--- a/packages/CarSystemUI/res/values-fa/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"حداقل"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"حداکثر"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"اکنون تشخیص صدا را دستگاه بلوتوث متصل کنترل می‌کند"</string>
- <string name="car_guest" msgid="318393171202663722">"مهمان"</string>
- <string name="start_guest_session" msgid="497784785761754874">"مهمان"</string>
- <string name="car_add_user" msgid="4067337059622483269">"افزودن کاربر"</string>
- <string name="car_new_user" msgid="6637442369728092473">"کاربر جدید"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"وقتی کاربر جدیدی اضافه می‌کنید، آن فرد باید فضای خود را تنظیم کند."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"هر کاربری می‌تواند برنامه‌ها را برای همه کاربران دیگر به‌روزرسانی کند."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"درحال بارگیری"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"بارگیری کاربر (از <xliff:g id="FROM_USER">%1$d</xliff:g> تا <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-fi/strings.xml b/packages/CarSystemUI/res/values-fi/strings.xml
deleted file mode 100644
index 6abf92ffa77a..000000000000
--- a/packages/CarSystemUI/res/values-fi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Alin"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Ylin"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Äänentunnistus tehdään nyt yhdistetyllä Bluetooth-laitteella"</string>
- <string name="car_guest" msgid="318393171202663722">"Vieras"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Vieras"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Lisää käyttäjä"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Uusi käyttäjä"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kun lisäät uuden käyttäjän, hänen on valittava oman tilansa asetukset."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Kaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Ladataan"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ladataan käyttäjäprofiilia (<xliff:g id="FROM_USER">%1$d</xliff:g>–<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-fr-rCA/strings.xml b/packages/CarSystemUI/res/values-fr-rCA/strings.xml
deleted file mode 100644
index 18e68c07d23d..000000000000
--- a/packages/CarSystemUI/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"La reconn. voc. est gérée par l\'appareil Bluetooth connecté"</string>
- <string name="car_guest" msgid="318393171202663722">"Invité"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Invité"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Ajouter un utilisateur"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nouvel utilisateur"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Tout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Chargement en cours…"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Chargement de l\'utilisateur (de <xliff:g id="FROM_USER">%1$d</xliff:g> vers <xliff:g id="TO_USER">%2$d</xliff:g>) en cours…"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-fr/strings.xml b/packages/CarSystemUI/res/values-fr/strings.xml
deleted file mode 100644
index 954df67d4b74..000000000000
--- a/packages/CarSystemUI/res/values-fr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"L\'appareil Bluetooth connecté gère la reconnaissance vocale"</string>
- <string name="car_guest" msgid="318393171202663722">"Invité"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Invité"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Ajouter un utilisateur"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nouvel utilisateur"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"N\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Chargement…"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Chargement de l\'utilisateur (de <xliff:g id="FROM_USER">%1$d</xliff:g> à <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-gl/strings.xml b/packages/CarSystemUI/res/values-gl/strings.xml
deleted file mode 100644
index 95bfbd30c0b8..000000000000
--- a/packages/CarSystemUI/res/values-gl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Máx."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"O dispositivo Bluetooth xestionará o recoñecemento de voz"</string>
- <string name="car_guest" msgid="318393171202663722">"Convidado"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Convidado"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Engadir usuario"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novo usuario"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cando engadas un novo usuario, este deberá configurar o seu espazo."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Calquera usuario pode actualizar as aplicacións para o resto dos usuarios."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (do <xliff:g id="FROM_USER">%1$d</xliff:g> ao <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-gu/strings.xml b/packages/CarSystemUI/res/values-gu/strings.xml
deleted file mode 100644
index dec991ce1400..000000000000
--- a/packages/CarSystemUI/res/values-gu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ન્યૂનતમ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"મહત્તમ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"અવાજની ઓળખ હવે કનેક્ટેડ બ્લૂટૂથ ડિવાઇસ વડે નિયંત્રિત થશે"</string>
- <string name="car_guest" msgid="318393171202663722">"અતિથિ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"અતિથિ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"વપરાશકર્તા ઉમેરો"</string>
- <string name="car_new_user" msgid="6637442369728092473">"નવા વપરાશકર્તા"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિએ તેમની સ્પેસ સેટ કરવાની જરૂર રહે છે."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"કોઈપણ વપરાશકર્તા અન્ય બધા વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"લોડ કરી રહ્યાં છીએ"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"વપરાશકર્તાને લોડ કરી રહ્યાં છીએ (<xliff:g id="FROM_USER">%1$d</xliff:g>માંથી <xliff:g id="TO_USER">%2$d</xliff:g>માં)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-hi/strings.xml b/packages/CarSystemUI/res/values-hi/strings.xml
deleted file mode 100644
index 89b69608efbe..000000000000
--- a/packages/CarSystemUI/res/values-hi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"कम से कम"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ज़्यादा से ज़्यादा"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"अब आवाज़ पहचानने का काम, कनेक्ट किए गए ब्लूटूथ डिवाइस करते हैं"</string>
- <string name="car_guest" msgid="318393171202663722">"मेहमान प्रोफ़ाइल"</string>
- <string name="start_guest_session" msgid="497784785761754874">"मेहमान के तौर पर सेशन शुरू करें"</string>
- <string name="car_add_user" msgid="4067337059622483269">"उपयोगकर्ता जोड़ें"</string>
- <string name="car_new_user" msgid="6637442369728092473">"नया उपयोगकर्ता"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं, तब उसे अपनी जगह सेट करनी होती है."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"कोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"लोड हो रही है"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"उपयोगकर्ता को लोड किया जा रहा है (<xliff:g id="FROM_USER">%1$d</xliff:g> से <xliff:g id="TO_USER">%2$d</xliff:g> पर)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-hr/strings.xml b/packages/CarSystemUI/res/values-hr/strings.xml
deleted file mode 100644
index 6baec74ddbff..000000000000
--- a/packages/CarSystemUI/res/values-hr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Prepoznavanjem glasa rukuje se s povezanog Bluetooth uređaja"</string>
- <string name="car_guest" msgid="318393171202663722">"Gost"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gost"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Dodajte korisnika"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može ažurirati aplikacije za ostale korisnike."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-hu/strings.xml b/packages/CarSystemUI/res/values-hu/strings.xml
deleted file mode 100644
index ffa512c4772a..000000000000
--- a/packages/CarSystemUI/res/values-hu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"A hangfelismerést a csatlakoztatott Bluetooth-eszköz kezeli"</string>
- <string name="car_guest" msgid="318393171202663722">"Vendég"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Vendég"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Felhasználó hozzáadása"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Új felhasználó"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Bármely felhasználó frissítheti az alkalmazásokat az összes felhasználó számára."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Betöltés"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Felhasználó betöltése (<xliff:g id="FROM_USER">%1$d</xliff:g> → <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-hy/strings.xml b/packages/CarSystemUI/res/values-hy/strings.xml
deleted file mode 100644
index ee6f74b4e5d8..000000000000
--- a/packages/CarSystemUI/res/values-hy/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Նվազ․"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Առավ․"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Ձայնի ճանաչումը մշակվում է միացված Bluetooth սարքի կողմից"</string>
- <string name="car_guest" msgid="318393171202663722">"Հյուր"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Հյուրի ռեժիմ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Ավելացնել օգտատեր"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Նոր օգտատեր"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Երբ դուք նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը։"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Ցանկացած օգտատեր կարող է թարմացնել հավելվածները բոլոր մյուս հաշիվների համար։"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Բեռնում"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Օգտատերը բեռնվում է (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-in/strings.xml b/packages/CarSystemUI/res/values-in/strings.xml
deleted file mode 100644
index 1145dc32dcb0..000000000000
--- a/packages/CarSystemUI/res/values-in/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Pengenalan suara ditangani perangkat Bluetooth terhubung"</string>
- <string name="car_guest" msgid="318393171202663722">"Tamu"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Tamu"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Tambahkan Pengguna"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Pengguna Baru"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Jika ditambahkan, pengguna baru harus menyiapkan ruangnya sendiri."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Setiap pengguna dapat mengupdate aplikasi untuk semua pengguna lain."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Memuat"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuat pengguna (dari <xliff:g id="FROM_USER">%1$d</xliff:g> menjadi <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-is/strings.xml b/packages/CarSystemUI/res/values-is/strings.xml
deleted file mode 100644
index 13e71366ebd3..000000000000
--- a/packages/CarSystemUI/res/values-is/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Lágm."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Hám."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Raddgreiningu er nú stjórnað af tengdu Bluetooth-tæki"</string>
- <string name="car_guest" msgid="318393171202663722">"Gestur"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gestur"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Bæta notanda við"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nýr notandi"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Þegar þú bætir nýjum notanda við þarf viðkomandi að setja upp sitt eigið svæði."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Allir notendur geta uppfært forrit fyrir alla aðra notendur."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Hleður"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Hleður notanda (frá <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-it/strings.xml b/packages/CarSystemUI/res/values-it/strings.xml
deleted file mode 100644
index f4f7ab719661..000000000000
--- a/packages/CarSystemUI/res/values-it/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Riconoscimento vocale gestito da dispos. Bluetooth connesso"</string>
- <string name="car_guest" msgid="318393171202663722">"Ospite"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Ospite"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Aggiungi utente"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nuovo utente"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Il nuovo utente, una volta aggiunto, dovrà configurare il suo spazio."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualsiasi utente può aggiornare le app per tutti gli altri."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Caricamento"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Caricamento dell\'utente (da <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-iw/strings.xml b/packages/CarSystemUI/res/values-iw/strings.xml
deleted file mode 100644
index a044b23709e1..000000000000
--- a/packages/CarSystemUI/res/values-iw/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"מינ\'"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"מקס\'"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"הזיהוי הקולי מתבצע עכשיו במכשיר Bluetooth מחובר"</string>
- <string name="car_guest" msgid="318393171202663722">"אורח"</string>
- <string name="start_guest_session" msgid="497784785761754874">"אורח"</string>
- <string name="car_add_user" msgid="4067337059622483269">"הוספת משתמש"</string>
- <string name="car_new_user" msgid="6637442369728092473">"משתמש חדש"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את המרחב שלו."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"כל משתמש יכול לעדכן אפליקציות לכל שאר המשתמשים."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"בטעינה"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"המשתמש בטעינה (מהמשתמש <xliff:g id="FROM_USER">%1$d</xliff:g> אל <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ja/strings.xml b/packages/CarSystemUI/res/values-ja/strings.xml
deleted file mode 100644
index aae7dbff155e..000000000000
--- a/packages/CarSystemUI/res/values-ja/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"最小"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"最大"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Bluetooth 接続デバイスで音声認識が処理されるようになりました"</string>
- <string name="car_guest" msgid="318393171202663722">"ゲスト"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ゲスト"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ユーザーを追加"</string>
- <string name="car_new_user" msgid="6637442369728092473">"新しいユーザー"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"どのユーザーも他のすべてのユーザーに代わってアプリを更新できます。"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"読み込んでいます"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ユーザーを読み込んでいます(<xliff:g id="FROM_USER">%1$d</xliff:g>~<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ka/strings.xml b/packages/CarSystemUI/res/values-ka/strings.xml
deleted file mode 100644
index 19894d164189..000000000000
--- a/packages/CarSystemUI/res/values-ka/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"მინ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"მაქს"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ხმის ამოცნობა დამუშავდება დაკავშირებული Bluetooth-მოწყობილობით"</string>
- <string name="car_guest" msgid="318393171202663722">"სტუმარი"</string>
- <string name="start_guest_session" msgid="497784785761754874">"სტუმარი"</string>
- <string name="car_add_user" msgid="4067337059622483269">"მომხმარებლის დამატება"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ახალი მომხმარებელი"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის გამართვა მოუწევს."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"იტვირთება"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"იტვირთება მომხმარებელი (<xliff:g id="FROM_USER">%1$d</xliff:g>-დან <xliff:g id="TO_USER">%2$d</xliff:g>-მდე)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-kk/strings.xml b/packages/CarSystemUI/res/values-kk/strings.xml
deleted file mode 100644
index 5220aa5bf1bd..000000000000
--- a/packages/CarSystemUI/res/values-kk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Дауысты тану үшін Bluetooth құрылғысы пайдаланылады."</string>
- <string name="car_guest" msgid="318393171202663722">"Қонақ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Қонақ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Пайдаланушыны енгізу"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Жаңа пайдаланушы"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Қосылған жаңа пайдаланушы өз профилін реттеуі керек."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Кез келген пайдаланушы қолданбаларды басқа пайдаланушылар үшін жаңарта алады."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Жүктелуде"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Пайдаланушы профилі жүктелуде (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-km/strings.xml b/packages/CarSystemUI/res/values-km/strings.xml
deleted file mode 100644
index fbcab8431476..000000000000
--- a/packages/CarSystemUI/res/values-km/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"អប្បបរមា"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"អតិបរិមា"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ឥឡូវនេះ ការសម្គាល់សំឡេងត្រូវបានចាត់ចែងដោយឧបករណ៍ដែលបានភ្ជាប់ប៊្លូធូស"</string>
- <string name="car_guest" msgid="318393171202663722">"ភ្ញៀវ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ភ្ញៀវ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"បញ្ចូល​អ្នក​ប្រើប្រាស់"</string>
- <string name="car_new_user" msgid="6637442369728092473">"អ្នក​ប្រើប្រាស់​ថ្មី"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"នៅពេលដែល​អ្នក​បញ្ចូល​អ្នក​ប្រើប្រាស់​ថ្មី បុគ្គល​នោះ​ត្រូវតែ​រៀបចំ​ទំហំ​ផ្ទុក​របស់គេ។"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"អ្នកប្រើប្រាស់​ណាក៏​អាច​ដំឡើងកំណែ​កម្មវិធី​សម្រាប់​អ្នកប្រើប្រាស់ទាំងអស់​ផ្សេងទៀត​បានដែរ។"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"កំពុងផ្ទុក"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"កំពុងផ្ទុក​អ្នកប្រើប្រាស់ (ពី <xliff:g id="FROM_USER">%1$d</xliff:g> ដល់ <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-kn/strings.xml b/packages/CarSystemUI/res/values-kn/strings.xml
deleted file mode 100644
index 21c4cc02e207..000000000000
--- a/packages/CarSystemUI/res/values-kn/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ಕನಿಷ್ಠ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ಗರಿಷ್ಠ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ಇದೀಗ ಕನೆಕ್ಟ್ ಆದ ಬ್ಲೂಟೂತ್ ಸಾಧನ ಧ್ವನಿ ಗುರುತಿಸುವಿಕೆ ನಿರ್ವಹಿಸಿದೆ"</string>
- <string name="car_guest" msgid="318393171202663722">"ಅತಿಥಿ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ಅತಿಥಿ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ಹೊಸ ಬಳಕೆದಾರ"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ನೀವು ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ಲೋಡ್ ಆಗುತ್ತಿದೆ"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ಬಳಕೆದಾರರನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ (<xliff:g id="FROM_USER">%1$d</xliff:g> ನಿಂದ <xliff:g id="TO_USER">%2$d</xliff:g> ವರೆಗೆ)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ko/strings.xml b/packages/CarSystemUI/res/values-ko/strings.xml
deleted file mode 100644
index 6b670b018814..000000000000
--- a/packages/CarSystemUI/res/values-ko/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"최소"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"최대"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"이제 연결된 블루투스 기기에서 음성 인식이 처리됩니다."</string>
- <string name="car_guest" msgid="318393171202663722">"게스트"</string>
- <string name="start_guest_session" msgid="497784785761754874">"게스트"</string>
- <string name="car_add_user" msgid="4067337059622483269">"사용자 추가"</string>
- <string name="car_new_user" msgid="6637442369728092473">"신규 사용자"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"추가된 신규 사용자는 자신만의 공간을 설정해야 합니다."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"누구나 다른 모든 사용자를 위해 앱을 업데이트할 수 있습니다."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"로드 중"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"사용자 로드 중(<xliff:g id="FROM_USER">%1$d</xliff:g>님에서 <xliff:g id="TO_USER">%2$d</xliff:g>님으로)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ky/strings.xml b/packages/CarSystemUI/res/values-ky/strings.xml
deleted file mode 100644
index b3b355a42aa8..000000000000
--- a/packages/CarSystemUI/res/values-ky/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Үндү эми туташкан Bluetooth түзмөгү менен тааныса болот"</string>
- <string name="car_guest" msgid="318393171202663722">"Конок"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Конок"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Колдонуучу кошуу"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Жаңы колдонуучу"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Жаңы колдонуучу кошулганда, ал өзүнүн профилин жөндөп алышы керек."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Колдонмолорду бир колдонуучу жаңыртканда, ал калган бардык колдонуучулар үчүн да жаңырат."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Жүктөлүүдө"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Колдонуучу тууралуу маалымат жүктөлүүдө (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-lo/strings.xml b/packages/CarSystemUI/res/values-lo/strings.xml
deleted file mode 100644
index d2199e2a0cef..000000000000
--- a/packages/CarSystemUI/res/values-lo/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ນທ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ສູງສຸດ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ການຈຳແນກສຽງເວົ້າດຽວນີ້ຈັດການໂດຍອຸປະກອນ Bluetooth ທີ່ເຊື່ອມຕໍ່"</string>
- <string name="car_guest" msgid="318393171202663722">"ແຂກ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ແຂກ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ເພີ່ມຜູ້ໃຊ້"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ຜູ້ໃຊ້ໃໝ່"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈຳເປັນຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າ."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ຜູ້ໃຊ້ຕ່າງໆສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ອື່ນທັງໝົດໄດ້."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ກຳລັງໂຫຼດ"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ກຳລັງໂຫຼດຜູ້ໃຊ້ (ຈາກ <xliff:g id="FROM_USER">%1$d</xliff:g> ໄປຍັງ <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-lt/strings.xml b/packages/CarSystemUI/res/values-lt/strings.xml
deleted file mode 100644
index 26690002416e..000000000000
--- a/packages/CarSystemUI/res/values-lt/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Didž."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Balso atpažinimą dabar tvarko susietas „Bluetooth“ įrenginys"</string>
- <string name="car_guest" msgid="318393171202663722">"Svečias"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Svečias"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Pridėti naudotoją"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Naujas naudotojas"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Bet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Įkeliama"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Įkeliamas naudotojo profilis (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-lv/strings.xml b/packages/CarSystemUI/res/values-lv/strings.xml
deleted file mode 100644
index 87b4ede4383a..000000000000
--- a/packages/CarSystemUI/res/values-lv/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Balss atpazīšanu tagad nodrošina pievienotā Bluetooth ierīce"</string>
- <string name="car_guest" msgid="318393171202663722">"Viesis"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Viesis"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Pievienot lietotāju"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Jauns lietotājs"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kad pievienojat jaunu lietotāju, viņam ir jāizveido savs profils."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Ikviens lietotājs var atjaunināt lietotnes visu lietotāju vārdā."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Notiek ielāde…"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Notiek lietotāja profila ielāde (<xliff:g id="FROM_USER">%1$d</xliff:g>–<xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-mk/strings.xml b/packages/CarSystemUI/res/values-mk/strings.xml
deleted file mode 100644
index f8fd02cb071d..000000000000
--- a/packages/CarSystemUI/res/values-mk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Поврзаниот уред со Bluetooth управува со препознавањето глас"</string>
- <string name="car_guest" msgid="318393171202663722">"Гостин"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Гостин"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Додај корисник"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Нов корисник"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Кога додавате нов корисник, тоа лице треба да го постави својот простор."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Секој корисник може да ажурира апликации за сите други корисници."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Се вчитува"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Се вчитува корисникот (од <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ml/strings.xml b/packages/CarSystemUI/res/values-ml/strings.xml
deleted file mode 100644
index 343157160105..000000000000
--- a/packages/CarSystemUI/res/values-ml/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"മിനിമം"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"മാക്സിമം"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"കണക്റ്റ് ചെയ്ത Bluetooth ഉപകരണം വഴി ഇപ്പോൾ വോയ്‌സ് തിരിച്ചറിയൽ കെെകാര്യം ചെയ്യുന്നു"</string>
- <string name="car_guest" msgid="318393171202663722">"അതിഥി"</string>
- <string name="start_guest_session" msgid="497784785761754874">"അതിഥി"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ഉപയോക്താവിനെ ചേർക്കുക"</string>
- <string name="car_new_user" msgid="6637442369728092473">"പുതിയ ഉപയോക്താവ്"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"നിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തി സ്വന്തം ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ഏതൊരു ഉപയോക്താവിനും മറ്റെല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്‌ഡേറ്റ് ചെയ്യാനാവും."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ലോഡ് ചെയ്യുന്നു"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ഉപയോക്തൃ പ്രൊഫൈൽ ലോഡ് ചെയ്യുന്നു (<xliff:g id="FROM_USER">%1$d</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="TO_USER">%2$d</xliff:g> എന്നതിലേക്ക്)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-mn/strings.xml b/packages/CarSystemUI/res/values-mn/strings.xml
deleted file mode 100644
index 5bd76dc7e067..000000000000
--- a/packages/CarSystemUI/res/values-mn/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Бага"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Их"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Одоо дуугаар танихыг холбогдсон Bluetooth төхөөрөмж удирдана"</string>
- <string name="car_guest" msgid="318393171202663722">"Зочин"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Зочин"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Хэрэглэгч нэмэх"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Шинэ хэрэглэгч"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Та шинэ хэрэглэгч нэмэх үед тухайн хэрэглэгч хувийн орон зайгаа тохируулах шаардлагатай."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Бусад бүх хэрэглэгчийн аппыг дурын хэрэглэгч шинэчлэх боломжтой."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Ачаалж байна"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Хэрэглэгчийг ачаалж байна (<xliff:g id="FROM_USER">%1$d</xliff:g>-с <xliff:g id="TO_USER">%2$d</xliff:g> хүртэл)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-mr/strings.xml b/packages/CarSystemUI/res/values-mr/strings.xml
deleted file mode 100644
index 2366465e1a9f..000000000000
--- a/packages/CarSystemUI/res/values-mr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"मि"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"कमाल"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"आता कनेक्ट केलेले ब्लूटूथ डिव्हाइस व्हॉइस रेकग्निशन हाताळते"</string>
- <string name="car_guest" msgid="318393171202663722">"अतिथी"</string>
- <string name="start_guest_session" msgid="497784785761754874">"अतिथी"</string>
- <string name="car_add_user" msgid="4067337059622483269">"वापरकर्ता जोडा"</string>
- <string name="car_new_user" msgid="6637442369728092473">"नवीन वापरकर्ता"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"तुम्ही नवीन वापरकर्ता जोडता तेव्हा त्या व्यक्तीने त्यांची जागा सेट करणे आवश्यक असते."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"कोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अ‍ॅप्स अपडेट करू शकतो."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"लोड करत आहे"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"वापरकर्ता लोड करत आहे (<xliff:g id="FROM_USER">%1$d</xliff:g> पासून <xliff:g id="TO_USER">%2$d</xliff:g> पर्यंत)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ms/strings.xml b/packages/CarSystemUI/res/values-ms/strings.xml
deleted file mode 100644
index 29ac83afc12c..000000000000
--- a/packages/CarSystemUI/res/values-ms/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Pengecaman suara kini dikendalikan peranti Bluetooth tersmbg"</string>
- <string name="car_guest" msgid="318393171202663722">"Tetamu"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Tetamu"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Tambah Pengguna"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Pengguna Baharu"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruang mereka."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Mana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Memuatkan"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuatkan pengguna (daripada <xliff:g id="FROM_USER">%1$d</xliff:g> hingga <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-my/strings.xml b/packages/CarSystemUI/res/values-my/strings.xml
deleted file mode 100644
index 7f240b430471..000000000000
--- a/packages/CarSystemUI/res/values-my/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"နိမ့်"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"မြင့်"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ချိတ်ထားသော ဘလူးတုသ်စက်ဖြင့် အသံမှတ်သားမှုကို ထိန်းချုပ်သည်"</string>
- <string name="car_guest" msgid="318393171202663722">"ဧည့်သည်"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ဧည့်သည်"</string>
- <string name="car_add_user" msgid="4067337059622483269">"အသုံးပြုသူ ထည့်ရန်"</string>
- <string name="car_new_user" msgid="6637442369728092473">"အသုံးပြုသူ အသစ်"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"အသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ နေရာကို စနစ်ထည့်သွင်းရပါမည်။"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"မည်သူမဆို အသုံးပြုသူအားလုံးအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်နိုင်သည်။"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ဖွင့်နေသည်"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"အသုံးပြုသူကို ဖွင့်နေသည် (<xliff:g id="FROM_USER">%1$d</xliff:g> မှ <xliff:g id="TO_USER">%2$d</xliff:g> သို့)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-nb/strings.xml b/packages/CarSystemUI/res/values-nb/strings.xml
deleted file mode 100644
index c1cfcf727859..000000000000
--- a/packages/CarSystemUI/res/values-nb/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Talegjenkjenning håndteres nå av tilkoblet Bluetooth-enhet"</string>
- <string name="car_guest" msgid="318393171202663722">"Gjest"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gjest"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Legg til bruker"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Ny bruker"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brukere kan oppdatere apper for alle andre brukere."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Laster inn"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Laster inn brukeren (fra <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ne/strings.xml b/packages/CarSystemUI/res/values-ne/strings.xml
deleted file mode 100644
index 40639dedc4b5..000000000000
--- a/packages/CarSystemUI/res/values-ne/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"न्यूनतम"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"अधिकतम"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"अब ब्लुटुथ मार्फत जोडिएको यन्त्रले आवाज पहिचान गर्ने कार्य सम्हाल्छ"</string>
- <string name="car_guest" msgid="318393171202663722">"अतिथि"</string>
- <string name="start_guest_session" msgid="497784785761754874">"अतिथि"</string>
- <string name="car_add_user" msgid="4067337059622483269">"प्रयोगकर्ता थप्नुहोस्"</string>
- <string name="car_new_user" msgid="6637442369728092473">"नयाँ प्रयोगकर्ता"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"तपाईंले नयाँ प्रयोगकर्ता थप्दा ती व्यक्तिले आफ्नो स्थान सेटअप गर्नु पर्छ।"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"सबै प्रयोगकर्ताले अन्य प्रयोगकर्ताका एपहरू अद्यावधिक गर्न सक्छन्।"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"लोड गरिँदै"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"प्रयोगकर्तासम्बन्धी जानकारी लोड गरिँदै (<xliff:g id="FROM_USER">%1$d</xliff:g> बाट <xliff:g id="TO_USER">%2$d</xliff:g> मा)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-nl/strings.xml b/packages/CarSystemUI/res/values-nl/strings.xml
deleted file mode 100644
index 95a76467b078..000000000000
--- a/packages/CarSystemUI/res/values-nl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Spraakherkenning actief via een verbonden bluetooth-apparaat"</string>
- <string name="car_guest" msgid="318393171202663722">"Gast"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gast"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Gebruiker toevoegen"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nieuwe gebruiker"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Als je een nieuwe gebruiker toevoegt, moet die persoon een eigen profiel instellen."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Elke gebruiker kan apps updaten voor alle andere gebruikers"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Laden"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Gebruiker laden (van <xliff:g id="FROM_USER">%1$d</xliff:g> naar <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-or/strings.xml b/packages/CarSystemUI/res/values-or/strings.xml
deleted file mode 100644
index b0b59b348594..000000000000
--- a/packages/CarSystemUI/res/values-or/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ସର୍ବନିମ୍ନ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ସର୍ବାଧିକ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ଭଏସ ଚିହ୍ନଟକରଣ ଏବେ ସଂଯୁକ୍ତ ଥିବା ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଦ୍ୱାରା ପରିଚାଳିତ"</string>
- <string name="car_guest" msgid="318393171202663722">"ଅତିଥି"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ଅତିଥି"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରନ୍ତୁ"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ଜଣେ ନୂଆ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରିବା ବେଳେ ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ତାଙ୍କ ସ୍ଥାନ ସେଟ୍ ଅପ୍ କରିବାର ଆବଶ୍ୟକତା ଅଛି।"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ଯେ କୌଣସି ଉପଯୋଗକର୍ତ୍ତା ଅନ୍ୟ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଆପଗୁଡ଼ିକୁ ଅପଡେଟ୍ କରିପାରିବେ।"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ଲୋଡ୍ କରାଯାଉଛି"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଲୋଡ୍ କରାଯାଉଛି (<xliff:g id="FROM_USER">%1$d</xliff:g>ଙ୍କ ଠାରୁ <xliff:g id="TO_USER">%2$d</xliff:g> ପର୍ଯ୍ୟନ୍ତ)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-pa/strings.xml b/packages/CarSystemUI/res/values-pa/strings.xml
deleted file mode 100644
index e7efca1894b7..000000000000
--- a/packages/CarSystemUI/res/values-pa/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"ਨਿਊਨਤਮ"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"ਅਧਿਕਤਮ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ਅਵਾਜ਼ ਦੀ ਪਛਾਣ ਨੂੰ ਹੁਣ ਕਨੈਕਟ ਕੀਤਾ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸ ਸੰਭਾਲਦਾ ਹੈ"</string>
- <string name="car_guest" msgid="318393171202663722">"ਮਹਿਮਾਨ"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ਮਹਿਮਾਨ"</string>
- <string name="car_add_user" msgid="4067337059622483269">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ਜਦੋਂ ਤੁਸੀਂ ਕੋਈ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ਵਰਤੋਂਕਾਰ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ (<xliff:g id="FROM_USER">%1$d</xliff:g> ਤੋਂ <xliff:g id="TO_USER">%2$d</xliff:g> ਤੱਕ)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-pl/strings.xml b/packages/CarSystemUI/res/values-pl/strings.xml
deleted file mode 100644
index 37d0ef171599..000000000000
--- a/packages/CarSystemUI/res/values-pl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Rozpoznawanie mowy przez połączone urządzenie Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Gość"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gość"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Dodaj użytkownika"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nowy użytkownik"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Każdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Ładuję"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ładuję użytkownika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-pt-rPT/strings.xml b/packages/CarSystemUI/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 182f5b58d1b1..000000000000
--- a/packages/CarSystemUI/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Máx."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Reconhecimento de voz agora através do disp. Bluetooth lig."</string>
- <string name="car_guest" msgid="318393171202663722">"Convidado"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Convidado"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Adicionar utilizador"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novo utilizador"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"A carregar…"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"A carregar o utilizador (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-pt/strings.xml b/packages/CarSystemUI/res/values-pt/strings.xml
deleted file mode 100644
index 5c8394a51599..000000000000
--- a/packages/CarSystemUI/res/values-pt/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Mín"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Máx"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Reconhecimento de voz com dispositivo Bluetooth conectado"</string>
- <string name="car_guest" msgid="318393171202663722">"Convidado"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Convidado"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Adicionar usuário"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Novo usuário"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer usuário pode atualizar apps para os demais usuários."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Carregando"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Carregando usuário (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ro/strings.xml b/packages/CarSystemUI/res/values-ro/strings.xml
deleted file mode 100644
index 25ecbb6453b0..000000000000
--- a/packages/CarSystemUI/res/values-ro/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Recunoașterea vocală acum gestionată de dispozitivul Bluetooth conectat"</string>
- <string name="car_guest" msgid="318393171202663722">"Invitat"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Invitat"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Adăugați un utilizator"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Utilizator nou"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Orice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Se încarcă"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Se încarcă utilizatorul (de la <xliff:g id="FROM_USER">%1$d</xliff:g> la <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ru/strings.xml b/packages/CarSystemUI/res/values-ru/strings.xml
deleted file mode 100644
index e93d25d1acdc..000000000000
--- a/packages/CarSystemUI/res/values-ru/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Для распознавания речи используется Bluetooth-устройство."</string>
- <string name="car_guest" msgid="318393171202663722">"Гость"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Гость"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Добавить пользователя"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Новый пользователь"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Когда вы добавите пользователя, ему потребуется настроить профиль."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Любой пользователь устройства может обновлять приложения для всех аккаунтов."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Загрузка…"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Загрузка профиля пользователя (с <xliff:g id="FROM_USER">%1$d</xliff:g> по <xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-si/strings.xml b/packages/CarSystemUI/res/values-si/strings.xml
deleted file mode 100644
index 947cb0a53206..000000000000
--- a/packages/CarSystemUI/res/values-si/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"අවම"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"උපරිම"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"හඬ හැඳුනුම දැන් සම්බන්ධ බ්ලූටූත් උපාංගය මගින් හසුරුවනු ලැබේ"</string>
- <string name="car_guest" msgid="318393171202663722">"අමුත්තා"</string>
- <string name="start_guest_session" msgid="497784785761754874">"අමුත්තා"</string>
- <string name="car_add_user" msgid="4067337059622483269">"පරිශීලක එක් කරන්න"</string>
- <string name="car_new_user" msgid="6637442369728092473">"නව පරිශීලක"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"ඔබ අලුත් පරිශීලකයෙකු එක් කරන විට, එම පුද්ගලයා තමන්ගේ ඉඩ සකසා ගැනීමට අවශ්‍ය වේ."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"සියලුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යෙදුම් යාවත්කාලීන කළ හැක."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"පූරණය වෙමින්"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"පරිශීලකයා පූරණය වෙමින් (<xliff:g id="FROM_USER">%1$d</xliff:g> සිට <xliff:g id="TO_USER">%2$d</xliff:g> වෙත)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sk/strings.xml b/packages/CarSystemUI/res/values-sk/strings.xml
deleted file mode 100644
index 2016b7b18adf..000000000000
--- a/packages/CarSystemUI/res/values-sk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"max."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Rozpoznávanie hlasu teraz prebieha v pripoj. zar. Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Hosť"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Hosť"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Pridať používateľa"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nový používateľ"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Každý používateľ môže aktualizovať aplikácie pre všetkých ostatných používateľov."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Načítava sa"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Načítava sa používateľ (predchádzajúci: <xliff:g id="FROM_USER">%1$d</xliff:g>, nasledujúci: <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sl/strings.xml b/packages/CarSystemUI/res/values-sl/strings.xml
deleted file mode 100644
index 32fd50e9cb8b..000000000000
--- a/packages/CarSystemUI/res/values-sl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Najn."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Najv."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Prepoznavanje glasu zdaj izvaja povezana naprava Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Gost"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gost"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Dodaj uporabnika"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Nov uporabnik"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Vsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Nalaganje"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nalaganje uporabnika (od uporabnika <xliff:g id="FROM_USER">%1$d</xliff:g> do uporabnika <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sq/strings.xml b/packages/CarSystemUI/res/values-sq/strings.xml
deleted file mode 100644
index 6fdd06c7d4d6..000000000000
--- a/packages/CarSystemUI/res/values-sq/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Njohja zanore trajtohet nga pajisja me Bluetooth-in e lidhur"</string>
- <string name="car_guest" msgid="318393171202663722">"I ftuar"</string>
- <string name="start_guest_session" msgid="497784785761754874">"I ftuar"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Shto përdorues"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Përdorues i ri"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Çdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Po ngarkohet"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Përdoruesi po ngarkohet (nga <xliff:g id="FROM_USER">%1$d</xliff:g> te <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sr/strings.xml b/packages/CarSystemUI/res/values-sr/strings.xml
deleted file mode 100644
index 494aeaa0f1f9..000000000000
--- a/packages/CarSystemUI/res/values-sr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мин."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maкс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Препознавањем гласа сада управља повезани Bluetooth уређај"</string>
- <string name="car_guest" msgid="318393171202663722">"Гост"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Гост"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Додај корисника"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Нови корисник"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Када додате новог корисника, та особа треба да подеси свој простор."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Сваки корисник може да ажурира апликације за све остале кориснике."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Учитава се"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Профил корисника се учитава (из<xliff:g id="FROM_USER">%1$d</xliff:g> у <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sv/strings.xml b/packages/CarSystemUI/res/values-sv/strings.xml
deleted file mode 100644
index 65481cdf2533..000000000000
--- a/packages/CarSystemUI/res/values-sv/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Nu hanteras röstigenkänning via en anstluten Bluetooth-enhet"</string>
- <string name="car_guest" msgid="318393171202663722">"Gäst"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Gäst"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Lägg till användare"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Ny användare"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Alla användare kan uppdatera appar för andra användare."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Läser in"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Läser in användare (från <xliff:g id="FROM_USER">%1$d</xliff:g> till <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-sw/strings.xml b/packages/CarSystemUI/res/values-sw/strings.xml
deleted file mode 100644
index a79d628e6786..000000000000
--- a/packages/CarSystemUI/res/values-sw/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Chini"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Juu"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Utambuzi wa sauti sasa unashughulikiwa na kifaa kilichounganishwa cha Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Mgeni"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Mgeni"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Ongeza Mtumiaji"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Mtumiaji Mpya"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ukiongeza mtumiaji mpya, ni lazima aweke kikundi chake."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Mtumiaji yeyote anaweza kusasisha programu za watumiaji wengine."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Inapakia"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Inapakia wasifu wa mtumiaji (kutoka <xliff:g id="FROM_USER">%1$d</xliff:g> kuwa <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ta/strings.xml b/packages/CarSystemUI/res/values-ta/strings.xml
deleted file mode 100644
index 849b40d36ccd..000000000000
--- a/packages/CarSystemUI/res/values-ta/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"குறைந்தபட்சம்"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"அதிகபட்சம்"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"இணைக்கப்பட்ட புளூடூத் சாதனத்தால் \'குரல் அறிதல்\' கையாளப்படுகிறது"</string>
- <string name="car_guest" msgid="318393171202663722">"கெஸ்ட்"</string>
- <string name="start_guest_session" msgid="497784785761754874">"கெஸ்ட்"</string>
- <string name="car_add_user" msgid="4067337059622483269">"பயனரைச் சேருங்கள்"</string>
- <string name="car_new_user" msgid="6637442369728092473">"புதிய பயனர்"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"புதிய பயனரைச் சேர்க்கும்போது அவர் தனக்கான சேமிப்பிடத்தை அமைக்க வேண்டும்."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"எந்தப் பயனரும் பிற பயனர்கள் சார்பாக ஆப்ஸைப் புதுப்பிக்க முடியும்."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"ஏற்றுகிறது"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"பயனர் தகவலை ஏற்றுகிறது (<xliff:g id="FROM_USER">%1$d</xliff:g>லிருந்து <xliff:g id="TO_USER">%2$d</xliff:g> வரை)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-te/strings.xml b/packages/CarSystemUI/res/values-te/strings.xml
deleted file mode 100644
index 83bb24a64a46..000000000000
--- a/packages/CarSystemUI/res/values-te/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"కని."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"గరి."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"నేడు వాయిస్ గుర్తింపును కనెక్ట్ అయిన బ్లూటూత్ నిర్వహిస్తోంది"</string>
- <string name="car_guest" msgid="318393171202663722">"గెస్ట్"</string>
- <string name="start_guest_session" msgid="497784785761754874">"గెస్ట్"</string>
- <string name="car_add_user" msgid="4067337059622483269">"యూజర్‌ను జోడించండి"</string>
- <string name="car_new_user" msgid="6637442369728092473">"కొత్త యూజర్"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"మీరు కొత్త యూజర్‌ను జోడించినప్పుడు, ఆ వ్యక్తి తన స్పేస్‌ను సెటప్ చేసుకోవాలి."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ఏ యూజర్ అయినా మిగతా యూజర్‌ల కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"లోడ్ అవుతోంది"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"యూజర్‌ను లోడ్ చేస్తోంది (<xliff:g id="FROM_USER">%1$d</xliff:g> నుండి <xliff:g id="TO_USER">%2$d</xliff:g> వరకు)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-th/strings.xml b/packages/CarSystemUI/res/values-th/strings.xml
deleted file mode 100644
index fa99ac1928c1..000000000000
--- a/packages/CarSystemUI/res/values-th/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"ตอนนี้อุปกรณ์บลูทูธที่เชื่อมต่อจะจัดการการจดจำเสียง"</string>
- <string name="car_guest" msgid="318393171202663722">"ผู้ใช้ชั่วคราว"</string>
- <string name="start_guest_session" msgid="497784785761754874">"ผู้ใช้ชั่วคราว"</string>
- <string name="car_add_user" msgid="4067337059622483269">"เพิ่มผู้ใช้"</string>
- <string name="car_new_user" msgid="6637442369728092473">"ผู้ใช้ใหม่"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"ผู้ใช้ทุกคนจะอัปเดตแอปให้แก่ผู้ใช้คนอื่นๆ ได้"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"กำลังโหลด"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"กำลังโหลดผู้ใช้ (จาก <xliff:g id="FROM_USER">%1$d</xliff:g> ถึง <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-tl/strings.xml b/packages/CarSystemUI/res/values-tl/strings.xml
deleted file mode 100644
index c6f5f59acf0d..000000000000
--- a/packages/CarSystemUI/res/values-tl/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Minuto"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Max"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Hawak na ngayon ng Bluetooth device ang Pagkilala ng boses"</string>
- <string name="car_guest" msgid="318393171202663722">"Bisita"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Bisita"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Magdagdag ng User"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Bagong User"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Puwedeng i-update ng sinumang user ang mga app para sa lahat ng iba pang user."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Naglo-load"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nilo-load ang user (mula kay <xliff:g id="FROM_USER">%1$d</xliff:g> papunta kay <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-tr/strings.xml b/packages/CarSystemUI/res/values-tr/strings.xml
deleted file mode 100644
index a76812769dae..000000000000
--- a/packages/CarSystemUI/res/values-tr/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Min."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Artık ses tanıma, bağlı Bluetooth cihazı tarafından işleniyor"</string>
- <string name="car_guest" msgid="318393171202663722">"Misafir"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Misafir"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Kullanıcı Ekle"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Yeni Kullanıcı"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yeni kullanıcı eklediğinizde, bu kişinin alanını ayarlaması gerekir."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Herhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Yükleniyor"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kullanıcı yükleniyor (<xliff:g id="FROM_USER">%1$d</xliff:g> kullanıcısından <xliff:g id="TO_USER">%2$d</xliff:g> kullanıcısına)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-uk/strings.xml b/packages/CarSystemUI/res/values-uk/strings.xml
deleted file mode 100644
index c424d87ace6e..000000000000
--- a/packages/CarSystemUI/res/values-uk/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Мін."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Макс."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Голос розпізнається через підключений пристрій Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Гість"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Гість"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Додати користувача"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Новий користувач"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Коли ви додаєте нового користувача, він має налаштувати свій профіль."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Усі користувачі можуть оновлювати додатки для решти людей."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Завантаження"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Завантаження профілю користувача (від <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-ur/strings.xml b/packages/CarSystemUI/res/values-ur/strings.xml
deleted file mode 100644
index 063dcbc4ecd1..000000000000
--- a/packages/CarSystemUI/res/values-ur/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"کم از کم"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"زیادہ سے زیادہ"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"آواز کی شناخت اب منسلک کردہ بلوٹوتھ آلے سے ہوتی ہے"</string>
- <string name="car_guest" msgid="318393171202663722">"مہمان"</string>
- <string name="start_guest_session" msgid="497784785761754874">"مہمان"</string>
- <string name="car_add_user" msgid="4067337059622483269">"صارف شامل کریں"</string>
- <string name="car_new_user" msgid="6637442369728092473">"نیا صارف"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ سیٹ کرنی ہوتی ہے۔"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"کوئی بھی صارف دیگر سبھی صارفین کے لیے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"لوڈ ہو رہی ہے"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"صارف کی نئی پروفائل لوڈ ہو رہی ہے (<xliff:g id="FROM_USER">%1$d</xliff:g> سے <xliff:g id="TO_USER">%2$d</xliff:g> کو)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-uz/strings.xml b/packages/CarSystemUI/res/values-uz/strings.xml
deleted file mode 100644
index adef2add435f..000000000000
--- a/packages/CarSystemUI/res/values-uz/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Daq."</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Maks."</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Endi ovozni tanish Bluetooth qurilma ulanganda amalga oshadi"</string>
- <string name="car_guest" msgid="318393171202663722">"Mehmon"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Mehmon"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Foydalanuvchi kiritish"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Yangi foydalanuvchi"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yangi profil kiritilgach, uni sozlash lozim."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Qurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Yuklanmoqda"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Foydalanuvchi profili yuklanmoqda (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-vi/strings.xml b/packages/CarSystemUI/res/values-vi/strings.xml
deleted file mode 100644
index 616b48fd17b6..000000000000
--- a/packages/CarSystemUI/res/values-vi/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Tối thiểu"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Tối đa"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Thiết bị Bluetooth được kết nối đang xử lý vấn đề nhận dạng giọng nói"</string>
- <string name="car_guest" msgid="318393171202663722">"Khách"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Khách"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Thêm người dùng"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Người dùng mới"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Khi bạn thêm một người dùng mới, người đó cần thiết lập không gian của mình."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Bất kỳ người dùng nào cũng có thể cập nhật ứng dụng cho tất cả những người dùng khác."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Đang tải"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Đang tải hồ sơ người dùng (từ <xliff:g id="FROM_USER">%1$d</xliff:g> sang <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rCN/strings.xml b/packages/CarSystemUI/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 6dc37382b25c..000000000000
--- a/packages/CarSystemUI/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"最小"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"最大"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"现在由已连接的蓝牙设备处理语音识别操作"</string>
- <string name="car_guest" msgid="318393171202663722">"访客"</string>
- <string name="start_guest_session" msgid="497784785761754874">"访客"</string>
- <string name="car_add_user" msgid="4067337059622483269">"添加用户"</string>
- <string name="car_new_user" msgid="6637442369728092473">"新用户"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"当您添加新用户时,该用户需要自行设置个人空间。"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"任何用户均可为所有其他用户更新应用。"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"正在加载"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在加载用户(从 <xliff:g id="FROM_USER">%1$d</xliff:g> 到 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rHK/strings.xml b/packages/CarSystemUI/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 00ebd3219ea3..000000000000
--- a/packages/CarSystemUI/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"最小"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"最大"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"現在由已連線的藍牙裝置處理語音辨識作業"</string>
- <string name="car_guest" msgid="318393171202663722">"訪客"</string>
- <string name="start_guest_session" msgid="497784785761754874">"訪客"</string>
- <string name="car_add_user" msgid="4067337059622483269">"新增使用者"</string>
- <string name="car_new_user" msgid="6637442369728092473">"新使用者"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"新增的使用者需要自行設定個人空間。"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都可以為所有其他使用者更新應用程式。"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"正在載入"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在載入使用者 (由 <xliff:g id="FROM_USER">%1$d</xliff:g> 至 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rTW/strings.xml b/packages/CarSystemUI/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 96d6a1d201be..000000000000
--- a/packages/CarSystemUI/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"最小"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"最大"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"現在由已連線的藍牙裝置處理語音辨識作業"</string>
- <string name="car_guest" msgid="318393171202663722">"訪客"</string>
- <string name="start_guest_session" msgid="497784785761754874">"訪客"</string>
- <string name="car_add_user" msgid="4067337059622483269">"新增使用者"</string>
- <string name="car_new_user" msgid="6637442369728092473">"新使用者"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"新使用者必須自行設定個人空間。"</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都能為所有其他使用者更新應用程式。"</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"載入中"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在載入使用者 (從 <xliff:g id="FROM_USER">%1$d</xliff:g> 到 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CarSystemUI/res/values-zu/strings.xml b/packages/CarSystemUI/res/values-zu/strings.xml
deleted file mode 100644
index b835f9a69bde..000000000000
--- a/packages/CarSystemUI/res/values-zu/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hvac_min_text" msgid="8167124789068494624">"Okuncane"</string>
- <string name="hvac_max_text" msgid="3669693372074755551">"Okuningi"</string>
- <string name="voice_recognition_toast" msgid="1149934534584052842">"Ukubonwa kwezwi manje kuphethwe idivayisi exhunyiwe ye-Bluetooth"</string>
- <string name="car_guest" msgid="318393171202663722">"Isihambeli"</string>
- <string name="start_guest_session" msgid="497784785761754874">"Isihambeli"</string>
- <string name="car_add_user" msgid="4067337059622483269">"Engeza umsebenzisi"</string>
- <string name="car_new_user" msgid="6637442369728092473">"Umsebenzisi omusha"</string>
- <string name="user_add_user_message_setup" msgid="1035578846007352323">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha izikhala zakhe."</string>
- <string name="user_add_user_message_update" msgid="7061671307004867811">"Noma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza zabanye abasebenzisi."</string>
- <string name="car_loading_profile" msgid="4507385037552574474">"Iyalayisha"</string>
- <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ilayisha umsebenzisi (kusuka ku-<xliff:g id="FROM_USER">%1$d</xliff:g> kuya ku-<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
-</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 16ef59f201f1..e501e1269aeb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -18,6 +18,8 @@ package com.android.companiondevicemanager;
import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
+import static java.util.Objects.requireNonNull;
+
import android.app.Activity;
import android.companion.CompanionDeviceManager;
import android.content.Intent;
@@ -117,6 +119,11 @@ public class DeviceChooserActivity extends Activity {
}
@Override
+ public String getCallingPackage() {
+ return requireNonNull(getService().mRequest.getCallingPackage());
+ }
+
+ @Override
public void setTitle(CharSequence title) {
final TextView titleView = findViewById(R.id.title);
final int padding = getPadding(getResources());
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
index fa738734c598..1049c3ca6b93 100644
--- a/packages/PackageInstaller/res/values-es/strings.xml
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -56,8 +56,8 @@
<string name="uninstall_application_text" msgid="3816830743706143980">"¿Quieres desinstalar esta aplicación?"</string>
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"¿Quieres desinstalar esta aplicación para "<b>"todos"</b>" los usuarios? La aplicación y sus datos se borrarán de "<b>"todos"</b>" los usuarios del dispositivo."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"¿Quieres desinstalar esta aplicación para el usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
- <string name="uninstall_update_text" msgid="863648314632448705">"¿Quieres reemplazar esta aplicación con la versión de fábrica? Ten en cuenta que se borrarán todos los datos."</string>
- <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"¿Quieres reemplazar esta aplicación con la versión de fábrica? Ten en cuenta que se borrarán todos los datos. Esto afecta a todos los usuarios del dispositivo, incluidos los que tienen perfiles de trabajo."</string>
+ <string name="uninstall_update_text" msgid="863648314632448705">"¿Quieres sustituir esta aplicación con la versión de fábrica? Ten en cuenta que se borrarán todos los datos."</string>
+ <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"¿Quieres sustituir esta aplicación con la versión de fábrica? Ten en cuenta que se borrarán todos los datos. Esto afecta a todos los usuarios del dispositivo, incluidos los que tienen perfiles de trabajo."</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"Mantener <xliff:g id="SIZE">%1$s</xliff:g> de datos de aplicaciones."</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstalaciones en curso"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstalaciones fallidas"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index d3a958922d1c..108c86fe8369 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="7488448184431507488">"Pakket-installatie"</string>
<string name="install" msgid="711829760615509273">"Installeren"</string>
- <string name="done" msgid="6632441120016885253">"Klaar"</string>
+ <string name="done" msgid="6632441120016885253">"Gereed"</string>
<string name="cancel" msgid="1018267193425558088">"Annuleren"</string>
<string name="installing" msgid="4921993079741206516">"Installeren…"</string>
<string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeren…"</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index 20a1ee369547..8c89ce9ca0eb 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -19,7 +19,7 @@
<string name="app_name" msgid="7488448184431507488">"ପ୍ୟାକେଜ୍‌ ଇନଷ୍ଟଲର୍‍"</string>
<string name="install" msgid="711829760615509273">"ଇନଷ୍ଟଲ୍‍ କରନ୍ତୁ"</string>
<string name="done" msgid="6632441120016885253">"ହୋଇଗଲା"</string>
- <string name="cancel" msgid="1018267193425558088">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="cancel" msgid="1018267193425558088">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
<string name="installing" msgid="4921993079741206516">"ଇନଷ୍ଟଲ୍‌ କରାଯାଉଛି…"</string>
<string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଇନଷ୍ଟଲ୍‌ କରାଯାଉଛି…"</string>
<string name="install_done" msgid="5987363587661783896">"ଆପ୍‍ ଇନଷ୍ଟଲ୍‌ ହୋଇଗଲା।"</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index 6fbee16e3dae..861a8ef0a910 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -105,7 +105,8 @@ public class InstallStart extends Activity {
}
Intent nextActivity = new Intent(intent);
- nextActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ nextActivity.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
// The the installation source as the nextActivity thinks this activity is the source, hence
// set the originating UID and sourceInfo explicitly
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
index be778e92787e..94829b506f95 100755
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -17,6 +17,7 @@
package com.android.packageinstaller;
import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static com.android.packageinstaller.PackageUtil.getMaxTargetSdkVersionForUid;
@@ -87,6 +88,8 @@ public class UninstallerActivity extends Activity {
@Override
public void onCreate(Bundle icicle) {
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
// Never restore any state, esp. never create any fragments. The data in the fragment might
// be stale, if e.g. the app was uninstalled while the activity was destroyed.
super.onCreate(null);
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index a346cb2c1b2d..98687b40af16 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"Gestor de cues d\'impressió"</string>
+ <string name="app_label" msgid="4469836075319831821">"Gest. cues impr."</string>
<string name="more_options_button" msgid="2243228396432556771">"Més opcions"</string>
<string name="label_destination" msgid="9132510997381599275">"Destinació"</string>
<string name="label_copies" msgid="3634531042822968308">"Còpies"</string>
diff --git a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
index 5b12fc586ef9..7ab3abcf7540 100644
--- a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-ar/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">"المساعدة والملاحظات والآراء"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والتعليقات"</string>
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml
index 150020cb17c5..759da1d0b021 100644
--- a/packages/SettingsLib/HelpUtils/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rAU/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">"Help and feedback"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Help &amp; feedback"</string>
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml
index 150020cb17c5..759da1d0b021 100644
--- a/packages/SettingsLib/HelpUtils/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rCA/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">"Help and feedback"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Help &amp; feedback"</string>
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml b/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml
index 150020cb17c5..759da1d0b021 100644
--- a/packages/SettingsLib/HelpUtils/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-en-rIN/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">"Help and feedback"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Help &amp; feedback"</string>
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml b/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
index 97e3559914a2..97ff5efc6401 100644
--- a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-es/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">"Ayuda y comentarios"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Ayuda y sugerencias"</string>
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-te/strings.xml b/packages/SettingsLib/HelpUtils/res/values-te/strings.xml
index 82c8613b5c8c..ea66717b1e87 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/RestrictedLockUtils/res/values-ar/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-ar/strings.xml
index 42cf76173a72..e26af95395a0 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-ar/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-ar/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"يفعِّل المشرف هذا الإعداد."</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"فعَّل المشرف هذا الإعداد."</string>
<string name="disabled_by_admin" msgid="4023569940620832713">"أوقف المشرف هذا الإعداد."</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml
index 7f10edf158b6..3a0bc2d2eb77 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-da/strings.xml
@@ -18,5 +18,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="enabled_by_admin" msgid="6630472777476410137">"Aktiveret af administratoren"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"Deaktiveret af administrator"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"Deaktiveret af administratoren"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-es/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-es/strings.xml
index 351f16cb1a24..4a6f73f0fcef 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-es/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-es/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"Habilitado por el administrador"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"Inhabilitado por el administrador"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"Habilitada por el administrador"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"Inhabilitada por el administrador"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml
index 2a881247c3af..aaf607f6f3ce 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-eu/strings.xml
@@ -18,5 +18,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="enabled_by_admin" msgid="6630472777476410137">"Administratzaileak gaitu egin du"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"Administratzaileak desgaitu du"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"Administratzaileak desgaitu egin du"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-fa/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-fa/strings.xml
index 9c39f98aab17..aaf9116bc9d5 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-fa/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-fa/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"توسط سرپرست فعال شده"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"توسط سرپرست غیرفعال شده"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"فعال‌شده توسط سرپرست"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"غیرفعال‌شده توسط سرپرست"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-ja/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-ja/strings.xml
index 490efd099569..7fcdbdfa7dab 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-ja/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-ja/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"管理者によって有効にされています"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"管理者により無効にされています"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"管理者が有効にしました"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"管理者が無効にしました"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-mr/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-mr/strings.xml
index 9c225f92f3bb..d4bac70ac4e7 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-mr/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-mr/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"अ‍ॅडमिनने सुरू केलेले"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"प्रशासकाने सुरू केलेले"</string>
<string name="disabled_by_admin" msgid="4023569940620832713">"प्रशासकाने बंद केलेले"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-or/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-or/strings.xml
index 4ce6460f8b89..6b1f2590f8e2 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-or/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-or/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"ଆଡମିନଙ୍କ ଦ୍ୱାରା ସକ୍ଷମ କରାଯାଇଛି"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"ଆଡମିନଙ୍କ ଦ୍ଵାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"ବ୍ୟବସ୍ଥାପକଙ୍କ ଦ୍ୱାରା ସକ୍ଷମ କରାଯାଇଛି"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"ବ୍ୟବସ୍ଥାପକଙ୍କ ଦ୍ଵାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-pt-rPT/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-pt-rPT/strings.xml
index 908e2fbbff5b..5cf0b29e14ff 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-pt-rPT/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"Ativado pelo administrador"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"Desativado pelo administrador"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"Ativada pelo administrador"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"Desativada pelo administrador"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-te/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-te/strings.xml
index 8f17dc5ec1e8..2da347c4454f 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-te/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-te/strings.xml
@@ -17,6 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enabled_by_admin" msgid="6630472777476410137">"అడ్మిన్ ఎనేబుల్ చేశారు"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"అడ్మిన్ డిజేబుల్ చేశారు"</string>
+ <string name="enabled_by_admin" msgid="6630472777476410137">"నిర్వాహకులు ప్రారంభించారు"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"నిర్వాహకులు నిలిపివేసారు"</string>
</resources>
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values-vi/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values-vi/strings.xml
index 2c37652c850e..f664bb444bc1 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/values-vi/strings.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values-vi/strings.xml
@@ -18,5 +18,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="enabled_by_admin" msgid="6630472777476410137">"Do quản trị viên bật"</string>
- <string name="disabled_by_admin" msgid="4023569940620832713">"Đã bị quản trị viên vô hiệu hóa"</string>
+ <string name="disabled_by_admin" msgid="4023569940620832713">"Bị quản trị viên tắt"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-be/strings.xml b/packages/SettingsLib/SearchWidget/res/values-be/strings.xml
index c72f8199f12e..4fc722faba52 100644
--- a/packages/SettingsLib/SearchWidget/res/values-be/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-be/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="search_menu" msgid="1914043873178389845">"Пошук налад"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Налады пошуку"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-el/strings.xml b/packages/SettingsLib/SearchWidget/res/values-el/strings.xml
index d50436a29ac1..6f5ab78b304b 100644
--- a/packages/SettingsLib/SearchWidget/res/values-el/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-el/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="search_menu" msgid="1914043873178389845">"Αναζήτηση στις ρυθμίσεις"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Ρυθμίσεις αναζήτησης"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml b/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml
index 9b735fece386..ed549db3c113 100644
--- a/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-es-rUS/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="search_menu" msgid="1914043873178389845">"Buscar configuraciones"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Buscar en la configuración"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml b/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml
index 2c9aaa5e9f95..fa5f9bdfe07b 100644
--- a/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-fa/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="search_menu" msgid="1914043873178389845">"تنظیمات جستجو"</string>
+ <string name="search_menu" msgid="1914043873178389845">"جستجوی تنظیمات"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-fr-rCA/strings.xml b/packages/SettingsLib/SearchWidget/res/values-fr-rCA/strings.xml
index 9977138f2079..6b2364d04cc6 100644
--- a/packages/SettingsLib/SearchWidget/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-fr-rCA/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="search_menu" msgid="1914043873178389845">"Rechercher dans les paramètres"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Paramètres de recherche"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-hi/strings.xml b/packages/SettingsLib/SearchWidget/res/values-hi/strings.xml
index 88c38316948a..975c320f9dba 100644
--- a/packages/SettingsLib/SearchWidget/res/values-hi/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-hi/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="search_menu" msgid="1914043873178389845">"सेटिंग में खोजें"</string>
+ <string name="search_menu" msgid="1914043873178389845">"खोज की सेटिंग"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml b/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml
index 34cb8e0fda38..9d83396689bd 100644
--- a/packages/SettingsLib/SearchWidget/res/values-hr/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-hr/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="search_menu" msgid="1914043873178389845">"Pretražite postavke"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Pretraži postavke"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-hy/strings.xml b/packages/SettingsLib/SearchWidget/res/values-hy/strings.xml
index b68b792acc32..8fa5a84acd79 100644
--- a/packages/SettingsLib/SearchWidget/res/values-hy/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-hy/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="search_menu" msgid="1914043873178389845">"Որոնեք կարգավորումներ"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Որոնման կարգավորումներ"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-in/strings.xml b/packages/SettingsLib/SearchWidget/res/values-in/strings.xml
index ccf11d26273c..edf51cc601ac 100644
--- a/packages/SettingsLib/SearchWidget/res/values-in/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-in/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="search_menu" msgid="1914043873178389845">"Telusuri setelan"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Setelan penelusuran"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-is/strings.xml b/packages/SettingsLib/SearchWidget/res/values-is/strings.xml
index 3378c84d7e08..7ab103b476f3 100644
--- a/packages/SettingsLib/SearchWidget/res/values-is/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-is/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="search_menu" msgid="1914043873178389845">"Leita í stillingum"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Leitarstillingar"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-pa/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pa/strings.xml
index 09a285b7452f..8c7dd6fe3ec6 100644
--- a/packages/SettingsLib/SearchWidget/res/values-pa/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-pa/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="search_menu" msgid="1914043873178389845">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਖੋਜੋ"</string>
+ <string name="search_menu" msgid="1914043873178389845">"ਖੋਜ ਸੈਟਿੰਗਾਂ"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml
index 5fe116e86f94..85a8d7342827 100644
--- a/packages/SettingsLib/SearchWidget/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-pt-rPT/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="search_menu" msgid="1914043873178389845">"Pesquisar nas definições"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Pesquisa de definições"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-sq/strings.xml b/packages/SettingsLib/SearchWidget/res/values-sq/strings.xml
index 354941d39e12..a5313210a6f9 100644
--- a/packages/SettingsLib/SearchWidget/res/values-sq/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-sq/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="search_menu" msgid="1914043873178389845">"Kërko te cilësimet"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Cilësimet e kërkimit"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-tl/strings.xml b/packages/SettingsLib/SearchWidget/res/values-tl/strings.xml
index 14b7b2f62eee..111cf5a15dba 100644
--- a/packages/SettingsLib/SearchWidget/res/values-tl/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-tl/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="search_menu" msgid="1914043873178389845">"Maghanap sa mga setting"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Mga setting ng paghahanap"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-uk/strings.xml b/packages/SettingsLib/SearchWidget/res/values-uk/strings.xml
index 560ac1359e5a..dfd66b28aa7a 100644
--- a/packages/SettingsLib/SearchWidget/res/values-uk/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-uk/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="search_menu" msgid="1914043873178389845">"Пошук налаштувань"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Налаштування пошуку"</string>
</resources>
diff --git a/packages/SettingsLib/SearchWidget/res/values-vi/strings.xml b/packages/SettingsLib/SearchWidget/res/values-vi/strings.xml
index 90daf11c712d..cb1a75a616f5 100644
--- a/packages/SettingsLib/SearchWidget/res/values-vi/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-vi/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="search_menu" msgid="1914043873178389845">"Tìm trong thông tin cài đặt"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Tìm kiếm trong các mục cài đặt"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index b19cde4f2778..a131a3b1ad91 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -40,7 +40,7 @@
<item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> এর সাথে কানেক্ট হচ্ছে…"</item>
<item msgid="3028983857109369308">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> দিয়ে যাচাইকরণ করা হচ্ছে..."</item>
<item msgid="4287401332778341890">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> থেকে আইপি অ্যাড্রেস জানা হচ্ছে…"</item>
- <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>-এ কানেক্ট হয়েছে"</item>
+ <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> তে কানেক্ট হয়েছে"</item>
<item msgid="7445993821842009653">"স্থগিত করা হয়েছে"</item>
<item msgid="1175040558087735707">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> থেকে ডিসকানেক্ট হচ্ছে…"</item>
<item msgid="699832486578171722">"ডিসকানেক্ট করা হয়েছে"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a5567d74b7b5..15ebfb88ea76 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -481,8 +481,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-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index fb4340db4cf8..6489cefdc551 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -187,7 +187,7 @@
<item msgid="97587758561106269">"Isključeno"</item>
<item msgid="7126170197336963369">"Međuspremnici svih zapisnika"</item>
<item msgid="7167543126036181392">"Međuspremnici svih zapisnika osim radija"</item>
- <item msgid="5135340178556563979">"samo međumemorija zapisnika kernela"</item>
+ <item msgid="5135340178556563979">"samo međuspremnik zapisnika kernela"</item>
</string-array>
<string-array name="window_animation_scale_entries">
<item msgid="2675263395797191850">"Animacija isključena"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 736c0f75d377..fd2635a9cbe5 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -394,7 +394,7 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu unean abian diren zerbitzuak"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ezarri WebView inplementazioa"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Jada ez dago erabilgarri aukera hori. Saiatu berriro."</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index d965b1209eeb..1407a50d7629 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -37,7 +37,7 @@
<string name="wifi_no_internet" msgid="1774198889176926299">"Sen acceso a Internet"</string>
<string name="saved_network" msgid="7143698034077223645">"Gardada por <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="connected_via_network_scorer" msgid="7665725527352893558">"Conectouse automaticamente a través de %1$s"</string>
- <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Conectada automaticamente a través dun provedor de valoración de redes"</string>
+ <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Conectada automaticamente a través dun provedor de valoración de rede"</string>
<string name="connected_via_passpoint" msgid="7735442932429075684">"Conectado a través de %1$s"</string>
<string name="connected_via_app" msgid="3532267661404276584">"Wifi conectada a través de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="available_via_passpoint" msgid="1716000261192603682">"Dispoñible a través de %1$s"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 16f470d3cd91..889857ab8829 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -481,8 +481,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 a70a0057410d..24153b9a04df 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -519,7 +519,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 f4015e8267af..61433be1549c 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ás"</string>
+ <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Bluetooth megosztása"</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/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 141ce3990800..a2de6dfc7387 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -55,7 +55,7 @@
</string-array>
<string-array name="hdcp_checking_summaries">
<item msgid="4045840870658484038">"Երբեք չօգտագործել HDCP ստուգումը"</item>
- <item msgid="8254225038262324761">"Օգտագործել HDCP-ը՝ միայն DRM-ի բովանդակությունը ստուգելու համար"</item>
+ <item msgid="8254225038262324761">"Օգտագործել HDCP-ը` միայն DRM-ի բովանդակությունը ստուգելու համար"</item>
<item msgid="6421717003037072581">"Միշտ օգտագործել HDCP ստուգումը"</item>
</string-array>
<string-array name="bt_hci_snoop_log_entries">
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 333a73503068..2e39f2cfdcb7 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>
@@ -339,7 +339,7 @@
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Թարմացվելիս ընդգծել սարքաշարի ծածկույթները կանաչ գույնով"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Վրիպազերծել GPU գերազանցումները"</string>
<string name="disable_overlays" msgid="4206590799671557143">"Կասեցնել HW վրադրումները"</string>
- <string name="disable_overlays_summary" msgid="1954852414363338166">"Միշտ օգտագործել GPU-ն՝ էկրանի կազմման համար"</string>
+ <string name="disable_overlays_summary" msgid="1954852414363338166">"Միշտ օգտագործել GPU-ն` էկրանի կազմման համար"</string>
<string name="simulate_color_space" msgid="1206503300335835151">"Նմանակել գունատարածքը"</string>
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ակտիվացնել OpenGL հետքերը"</string>
<string name="usb_audio_disable_routing" msgid="3367656923544254975">"Անջատել USB աուդիո երթուղումը"</string>
@@ -487,7 +487,7 @@
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Ավելացնել ժամանակը:"</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Պակասեցնել ժամանակը:"</string>
<string name="cancel" msgid="5665114069455378395">"Չեղարկել"</string>
- <string name="okay" msgid="949938843324579502">"Եղավ"</string>
+ <string name="okay" msgid="949938843324579502">"Հաստատել"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Միացնել"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Միացրեք «Չանհանգստացնել» ռեժիմը"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Երբեք"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index d20bf38024ab..e73febcb1aa4 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -40,7 +40,7 @@
<item msgid="8339720953594087771">"Menyambung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
<item msgid="3028983857109369308">"Mengautentikasi dengan <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
<item msgid="4287401332778341890">"Mendapatkan alamat IP dari <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
- <item msgid="1043944043827424501">"Terhubung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+ <item msgid="1043944043827424501">"Tersambung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
<item msgid="7445993821842009653">"Ditangguhkan"</item>
<item msgid="1175040558087735707">"Diputus dari <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
<item msgid="699832486578171722">"Sambungan terputus"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 792b75ae09da..b75fa357b938 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -156,7 +156,7 @@
<string name="launch_defaults_none" msgid="8049374306261262709">"Tidak ada setelan default"</string>
<string name="tts_settings" msgid="8130616705989351312">"Setelan text-to-speech"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"Keluaran text-to-speech"</string>
- <string name="tts_default_rate_title" msgid="3964187817364304022">"Kecepatan ucapan"</string>
+ <string name="tts_default_rate_title" msgid="3964187817364304022">"Laju bicara"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"Kecepatan teks diucapkan"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"Tinggi nada"</string>
<string name="tts_default_pitch_summary" msgid="9132719475281551884">"Memengaruhi nada ucapan yang disintesis"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index fd2f2c1818d6..0bca8ea75212 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -22,13 +22,13 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="wifi_status">
<item msgid="1596683495752107015"></item>
- <item msgid="3288373008277313483">"Scansione in corso…"</item>
- <item msgid="6050951078202663628">"Connessione…"</item>
- <item msgid="8356618438494652335">"Autenticazione…"</item>
- <item msgid="2837871868181677206">"Acquisizione indirizzo IP…"</item>
+ <item msgid="3288373008277313483">"Scansione in corso..."</item>
+ <item msgid="6050951078202663628">"Connessione..."</item>
+ <item msgid="8356618438494652335">"Autenticazione..."</item>
+ <item msgid="2837871868181677206">"Acquisizione indirizzo IP..."</item>
<item msgid="4613015005934755724">"Connessa"</item>
<item msgid="3763530049995655072">"Sospesa"</item>
- <item msgid="7852381437933824454">"Disconnessione…"</item>
+ <item msgid="7852381437933824454">"Disconnessione..."</item>
<item msgid="5046795712175415059">"Disconnessa"</item>
<item msgid="2473654476624070462">"Operazione non riuscita"</item>
<item msgid="9146847076036105115">"Bloccato"</item>
@@ -36,13 +36,13 @@
</string-array>
<string-array name="wifi_status_with_ssid">
<item msgid="5969842512724979061"></item>
- <item msgid="1818677602615822316">"Scansione in corso…"</item>
- <item msgid="8339720953594087771">"Connessione a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
- <item msgid="3028983857109369308">"Autenticazione con <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
- <item msgid="4287401332778341890">"Acquisizione indirizzo IP da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="1818677602615822316">"Scansione in corso..."</item>
+ <item msgid="8339720953594087771">"Connessione a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
+ <item msgid="3028983857109369308">"Autenticazione con <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
+ <item msgid="4287401332778341890">"Acquisizione indirizzo IP da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
<item msgid="1043944043827424501">"Connessa a <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
<item msgid="7445993821842009653">"Sospesa"</item>
- <item msgid="1175040558087735707">"Disconnessione da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="1175040558087735707">"Disconnessione da <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
<item msgid="699832486578171722">"Disconnessa"</item>
<item msgid="522383512264986901">"Operazione non riuscita"</item>
<item msgid="3602596701217484364">"Bloccato"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index d166c179757c..2966f09c6c1b 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -40,7 +40,7 @@
<item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>に接続中..."</item>
<item msgid="3028983857109369308">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>による認証中..."</item>
<item msgid="4287401332778341890">"IPアドレスを<xliff:g id="NETWORK_NAME">%1$s</xliff:g>から取得中..."</item>
- <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> に接続済み"</item>
+ <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>に接続しました"</item>
<item msgid="7445993821842009653">"保留中"</item>
<item msgid="1175040558087735707">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>から切断中..."</item>
<item msgid="699832486578171722">"切断されました"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 895e450a59c5..2070056fad14 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -390,8 +390,8 @@
<item msgid="1282170165150762976">"Санарип мазмун үчүн оптималдаштырылган түстөр"</item>
</string-array>
<string name="inactive_apps_title" msgid="5372523625297212320">"Көшүү режиминдеги колдонмолор"</string>
- <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Күйгүзүү үчүн басып коюңуз."</string>
- <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string>
+ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Которуштуруу үчүн таптап коюңуз."</string>
+ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 6db2404d95eb..ae2df9a9e76f 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -204,10 +204,10 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"Поставките за спојување не се достапни за овој корисник"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"Поставките за името на пристапната точка не се достапни за овој корисник"</string>
<string name="enable_adb" msgid="8072776357237289039">"Отстранување грешки на USB"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"Режим за отстранување грешки кога е поврзано USB"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"Режим на отстранување грешки кога е поврзано USB"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"Отповикај овластувања за отстранување грешки од USB"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Безжично отстранување грешки"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим за отстранување грешки кога е поврзано Wi‑Fi"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим на отстранување грешки кога е поврзано Wi‑Fi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Безжично отстранување грешки"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"За да ги гледате и користите достапните уреди, вклучете го безжичното отстранување грешки"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 43e4e6664d1f..5d79e80608d0 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -238,7 +238,7 @@
</string-array>
<string-array name="show_non_rect_clip_entries">
<item msgid="2482978351289846212">"बन्द"</item>
- <item msgid="3405519300199774027">"गैर आयातकार क्षेत्र निलो रङमा कोर्नुहोस्"</item>
+ <item msgid="3405519300199774027">"गैर आयातकार क्षेत्र नीलो रङमा कोर्नुहोस्"</item>
<item msgid="1212561935004167943">"हाइलाइट परीक्षण चित्र कोर्ने आदेशहरू हरियोमा"</item>
</string-array>
<string-array name="track_frame_time_entries">
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 79bb43db9d05..e11f02d0bc04 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 a5714c3ba842..3ca705f71e18 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">"Sambaza mtandao kwa USB"</string>
+ <string name="tether_settings_title_usb" msgid="3728686573430917722">"Shiriki intaneti kwa USB"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"Intaneti ya kusambazwa"</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="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="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-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index aa0da1231bed..e34c548b68e2 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/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 03161d051342..fb695e50ed7c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1100,6 +1100,8 @@
<string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until charged</string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until charged</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charge been limited -->
+ <string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Optimizing for battery health</string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="battery_info_status_unknown">Unknown</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index b2808061586b..9e59ce3ea166 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -14,6 +14,9 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.location.LocationManager;
@@ -303,6 +306,36 @@ public class Utils {
}
/**
+ * Create a color matrix suitable for a ColorMatrixColorFilter that modifies only the color but
+ * preserves the alpha for a given drawable
+ * @param color
+ * @return a color matrix that uses the source alpha and given color
+ */
+ public static ColorMatrix getAlphaInvariantColorMatrixForColor(@ColorInt int color) {
+ int r = Color.red(color);
+ int g = Color.green(color);
+ int b = Color.blue(color);
+
+ ColorMatrix cm = new ColorMatrix(new float[] {
+ 0, 0, 0, 0, r,
+ 0, 0, 0, 0, g,
+ 0, 0, 0, 0, b,
+ 0, 0, 0, 1, 0 });
+
+ return cm;
+ }
+
+ /**
+ * Create a ColorMatrixColorFilter to tint a drawable but retain its alpha characteristics
+ *
+ * @return a ColorMatrixColorFilter which changes the color of the output but is invariant on
+ * the source alpha
+ */
+ public static ColorFilter getAlphaInvariantColorFilterForColor(@ColorInt int color) {
+ return new ColorMatrixColorFilter(getAlphaInvariantColorMatrixForColor(color));
+ }
+
+ /**
* Determine whether a package is a "system package", in which case certain things (like
* disabling notifications or disabling the package altogether) should be disallowed.
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index a5b5312707d0..5fa04f93e993 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -108,6 +108,7 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
private val fillColorStrokePaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
p.color = frameColor
+ p.alpha = 255
p.isDither = true
p.strokeWidth = 5f
p.style = Paint.Style.STROKE
@@ -145,7 +146,7 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
// Only used if dualTone is set to true
private val dualToneBackgroundFill = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
p.color = frameColor
- p.alpha = 255
+ p.alpha = 85 // ~0.3 alpha by default
p.isDither = true
p.strokeWidth = 0f
p.style = Paint.Style.FILL_AND_STROKE
diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml
index 946e2c07c576..cc0b55728310 100644
--- a/packages/SettingsProvider/res/values-fa/strings.xml
+++ b/packages/SettingsProvider/res/values-fa/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4567566098528588863">"تنظیم محل فضای ذخیره‌سازی"</string>
+ <string name="app_label" msgid="4567566098528588863">"تنظیم محل ذخیره"</string>
<string name="wifi_softap_config_change" msgid="5688373762357941645">"تنظیمات نقطه اتصال تغییر کرده است"</string>
<string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"برای مشاهده جزئیات ضربه بزنید"</string>
</resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index dc55986faf29..7d04eeb9165f 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -21,7 +21,7 @@
<string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generazione segnalazione di bug <xliff:g id="ID">#%d</xliff:g> in corso"</string>
<string name="bugreport_finished_title" msgid="4429132808670114081">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita"</string>
<string name="bugreport_updating_title" msgid="4423539949559634214">"Aggiunta di dettagli alla segnalazione di bug"</string>
- <string name="bugreport_updating_wait" msgid="3322151947853929470">"Attendi…"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Attendi..."</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"La segnalazione di bug comparirà a breve sul telefono"</string>
<string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Seleziona per condividere la segnalazione di bug"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tocca per condividere la segnalazione di bug"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 65e3f0dbd176..6d86a78360d8 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_pin_accepted" msgid="1625501841604389716">"تم قبول الرمز"</string>
<string name="keyguard_carrier_default" msgid="6359808469637388586">"لا تتوفر خدمة."</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"تبديل أسلوب الإدخال"</string>
- <string name="airplane_mode" msgid="2528005343938497866">"وضع الطيران"</string>
+ <string name="airplane_mode" msgid="2528005343938497866">"وضع الطائرة"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"يجب رسم النقش بعد إعادة تشغيل الجهاز"</string>
<string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز"</string>
<string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index ea07c3db4354..d63c23f4d1f6 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Şifrənizi daxil edin"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Yanlış PIN kod."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Yanlış Kart."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Enerji yığılıb"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Enerji yığdı"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz şəkildə batareya yığır"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 0754681215cc..ce323c7f65a7 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduce tu contraseña"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"El código PIN es incorrecto."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Tarjeta no válida."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Cargada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sin cables"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 46079810aee4..420649eeca60 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduce o contrasinal"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorrecto"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"A tarxeta non é válida."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Cargada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sen fíos"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 85b2a4726fa2..875d8d51c50b 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Masukkan sandi"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Kode PIN salah."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kartu Tidak Valid"</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Terisi penuh"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Terisi"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya secara nirkabel"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index e1c9ee8b7d34..16767d1771fe 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -48,7 +48,7 @@
<string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"La scheda SIM è stata disattivata definitivamente.\n Contatta il fornitore del tuo servizio wireless per ricevere un\'altra scheda SIM."</string>
<string name="keyguard_sim_locked_message" msgid="4343544458476911044">"La SIM è bloccata."</string>
<string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"La SIM è bloccata tramite PUK."</string>
- <string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"Sblocco SIM…"</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"Sblocco SIM..."</string>
<string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"Area PIN"</string>
<string name="keyguard_accessibility_password" msgid="3524161948484801450">"Password del dispositivo"</string>
<string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Area PIN SIM"</string>
@@ -77,7 +77,7 @@
<string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" non è attiva al momento. Inserisci il codice PUK per continuare. Contatta l\'operatore per avere informazioni dettagliate."</string>
<string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Inserisci il codice PIN desiderato"</string>
<string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Conferma il codice PIN desiderato"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Sblocco SIM…"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Sblocco SIM..."</string>
<string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Il PIN deve essere di 4-8 numeri."</string>
<string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Il codice PUK dovrebbe avere almeno otto numeri."</string>
<string name="kg_invalid_puk" msgid="1774337070084931186">"Inserisci di nuovo il codice PUK corretto. Ripetuti tentativi comportano la disattivazione definitiva della scheda SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 62afd1e45df8..96972a7577cf 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -70,7 +70,7 @@
<string name="kg_pattern_instructions" msgid="5376036737065051736">"Өрнекті енгізіңіз"</string>
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN кодын енгізіңіз."</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" үшін SIM PIN кодын енгізіңіз."</string>
- <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Құрылғыны мобильдік байланыс қызметінсіз пайдалану үшін eSIM картасын өшіріңіз."</string>
+ <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Құрылығыны мобильдік байланыс қызметінсіз пайдалану үшін eSIM картасын өшіріңіз."</string>
<string name="kg_pin_instructions" msgid="822353548385014361">"PIN кодын енгізіңіз"</string>
<string name="kg_password_instructions" msgid="324455062831719903">"Кілтсөзді енгізіңіз"</string>
<string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. Толығырақ ақпаратты оператордан алыңыз."</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 52b7fab768c5..24b5c23a6732 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -100,7 +100,7 @@
<string name="kg_pin_accepted" msgid="1625501841604389716">"កូដត្រូវ​បានទទួល​យក!"</string>
<string name="keyguard_carrier_default" msgid="6359808469637388586">"គ្មាន​សេវា​ទេ។"</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ប្ដូរ​វិធី​បញ្ចូល"</string>
- <string name="airplane_mode" msgid="2528005343938497866">"​ពេល​ជិះ​យន្តហោះ"</string>
+ <string name="airplane_mode" msgid="2528005343938497866">"មុខងារ​ពេល​ជិះ​យន្តហោះ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"តម្រូវឲ្យប្រើលំនាំ បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"តម្រូវឲ្យបញ្ចូលកូដ PIN បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
<string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"តម្រូវឲ្យបញ្ចូលពាក្យសម្ងាត់ បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 848490ebb9b8..6ae5935fea1a 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -62,7 +62,7 @@
<string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"패턴을 잊음"</string>
<string name="kg_wrong_pattern" msgid="5907301342430102842">"잘못된 패턴"</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"잘못된 비밀번호"</string>
- <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 오류"</string>
+ <string name="kg_wrong_pin" msgid="4160978845968732624">"잘못된 PIN"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
<item quantity="other"><xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요.</item>
<item quantity="one">1초 후에 다시 시도하세요.</item>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index d868788a3eca..9675cc9d39b2 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -45,7 +45,7 @@
<string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"SIM-карта салыңыз."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"SIM-карта жок же ал окулбай калган. SIM-карта салыңыз."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"Жараксыз SIM-карта."</string>
- <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"SIM картаңыз биротоло өчүрүлдү.\n Башка SIM-карта алыш үчүн зымсыз кызмат көрсөтүүчүгө кайрылыңыз."</string>
+ <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"SIM-картаңыз биротоло өчүрүлдү.\n Башка SIM-карта алыш үчүн зымсыз кызмат көрсөтүүчүгө кайрылыңыз."</string>
<string name="keyguard_sim_locked_message" msgid="4343544458476911044">"SIM-карта кулпуланган."</string>
<string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"SIM-карта PUK-код менен кулпуланган."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"SIM-карта бөгөттөн чыгарылууда…"</string>
@@ -80,7 +80,7 @@
<string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-карта бөгөттөн чыгарылууда…"</string>
<string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4–8 сандан турган PIN-кодду териңиз."</string>
<string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код 8 же андан көп сандан турушу керек."</string>
- <string name="kg_invalid_puk" msgid="1774337070084931186">"PUK-кодду кайрадан туура киргизиңиз. Кайталанган аракеттер SIM картаны биротоло жараксыз кылат."</string>
+ <string name="kg_invalid_puk" msgid="1774337070084931186">"PUK-кодду кайрадан туура киргизиңиз. Кайталанган аракеттер SIM-картаны биротоло жараксыз кылат."</string>
<string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Өтө көп графикалык ачкычты тартуу аракети болду"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
@@ -98,7 +98,7 @@
<string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-картанын PIN-кодун ачуу кыйрады!"</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-картанын PUK-кодун ачуу кыйрады!"</string>
<string name="kg_pin_accepted" msgid="1625501841604389716">"Код кабыл алынды!"</string>
- <string name="keyguard_carrier_default" msgid="6359808469637388586">"Интернет жок."</string>
+ <string name="keyguard_carrier_default" msgid="6359808469637388586">"Байланыш жок."</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Киргизүү ыкмасын өзгөртүү"</string>
<string name="airplane_mode" msgid="2528005343938497866">"Учак режими"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Түзмөк кайра күйгүзүлгөндөн кийин графикалык ачкычты тартуу талап кылынат"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index ce05e38dca10..0cec32e9a90c 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -60,7 +60,7 @@
<string name="error_disable_esim_msg" msgid="2441188596467999327">"कुनै त्रुटिका कारण यो eSIM लाई असक्षम पार्न सकिएन।"</string>
<string name="keyboardview_keycode_enter" msgid="6727192265631761174">"प्रविष्टि गर्नुहोस्"</string>
<string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ढाँचा बिर्सनुभयो"</string>
- <string name="kg_wrong_pattern" msgid="5907301342430102842">"प्याटर्न मिलेन"</string>
+ <string name="kg_wrong_pattern" msgid="5907301342430102842">"गलत ढाँचा"</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"गलत पासवर्ड"</string>
<string name="kg_wrong_pin" msgid="4160978845968732624">"गलत PIN"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 5094cf9983a1..9b6f857456d6 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -54,7 +54,7 @@
<string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Miejsce na kod PIN karty SIM"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Miejsce na kod PUK karty SIM"</string>
<string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Następny alarm ustawiony na: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
- <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Usuń"</string>
+ <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Usuwanie"</string>
<string name="disable_carrier_button_text" msgid="7153361131709275746">"Wyłącz eSIM"</string>
<string name="error_disable_esim_title" msgid="3802652622784813119">"Nie można wyłączyć karty eSIM"</string>
<string name="error_disable_esim_msg" msgid="2441188596467999327">"Nie można wyłączyć karty eSIM z powodu błędu."</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 5bfc3dbc900d..cc0c044c445a 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Digite sua senha"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorreto."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 5bfc3dbc900d..cc0c044c445a 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Digite sua senha"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorreto."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 967255cb50e7..a141ed7ffaa6 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Vnesite geslo"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Napačna koda PIN."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neveljavna kartica"</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Baterija napolnjena"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Akumulator napolnjen"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brezžično polnjenje"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 382a4dcafed7..1d34e3f8e099 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Fut fjalëkalimin"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Kodi PIN është i pasaktë."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Karta e pavlefshme."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"I karikuar"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"I ngarkuar"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me valë"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index d44003bc5b95..74386bc7a487 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-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index e157be4ac18e..aa9e693db0fa 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -135,6 +135,6 @@
<item quantity="one">ซิมถูกปิดใช้งานในขณะนี้ โปรดป้อนรหัส PUK เพื่อทำต่อ คุณพยายามได้อีก <xliff:g id="_NUMBER_0">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ</item>
</plurals>
<string name="clock_title_default" msgid="6342735240617459864">"ค่าเริ่มต้น"</string>
- <string name="clock_title_bubble" msgid="2204559396790593213">"บับเบิล"</string>
+ <string name="clock_title_bubble" msgid="2204559396790593213">"ลูกโป่ง"</string>
<string name="clock_title_analog" msgid="8409262532900918273">"แอนะล็อก"</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 0fd5e17c953e..7b946aaf40da 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -71,7 +71,7 @@
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏SIM PIN درج کریں۔"</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏\"<xliff:g id="CARRIER">%1$s</xliff:g>\" کیلئے SIM PIN درج کریں۔"</string>
<string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‏<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> موبائل سروس کے بغیر آلہ کا استعمال کرنے کیلئے eSIM غیر فعال کریں۔"</string>
- <string name="kg_pin_instructions" msgid="822353548385014361">"‏‫PIN درج کریں"</string>
+ <string name="kg_pin_instructions" msgid="822353548385014361">"‏PIN درج کریں"</string>
<string name="kg_password_instructions" msgid="324455062831719903">"پاسورڈ درج کریں"</string>
<string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‏SIM اب غیر فعال ہوگیا ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔"</string>
<string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" اب غیر فعال ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 323fea5a608e..a6c2aa055c0b 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -33,7 +33,7 @@
<string name="keyguard_enter_your_password" msgid="7225626204122735501">"Parolni kiriting"</string>
<string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kodi xato."</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM karta yaroqsiz."</string>
- <string name="keyguard_charged" msgid="5478247181205188995">"Quvvat oldi"</string>
+ <string name="keyguard_charged" msgid="5478247181205188995">"Batareya quvvati to‘ldi"</string>
<string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz quvvatlanyapti"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 2ba5089c7ed9..31737fca5e4d 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -60,7 +60,7 @@
<string name="error_disable_esim_msg" msgid="2441188596467999327">"Không thể tắt eSIM do lỗi."</string>
<string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Nhập"</string>
<string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Đã quên hình mở khóa"</string>
- <string name="kg_wrong_pattern" msgid="5907301342430102842">"Hình mở khóa không chính xác"</string>
+ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Hình không chính xác"</string>
<string name="kg_wrong_password" msgid="4143127991071670512">"Mật khẩu sai"</string>
<string name="kg_wrong_pin" msgid="4160978845968732624">"Mã PIN sai"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index f7e9fedd5f66..4b6621379b44 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -79,6 +79,9 @@
is not fully charged, and it's plugged into a slow charger, say that it's charging slowly. -->
<string name="keyguard_plugged_in_charging_slowly"><xliff:g id="percentage">%s</xliff:g> • Charging slowly</string>
+ <!-- When the lock screen is showing and the phone plugged in, and the defend mode is triggered, say that it's optimizing for battery health. -->
+ <string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Optimizing for battery health</string>
+
<!-- When the lock screen is showing and the battery is low, warn user to plug
in the phone soon. -->
<string name="keyguard_low_battery">Connect your charger.</string>
diff --git a/packages/SystemUI/res/layout/controls_dialog_pin.xml b/packages/SystemUI/res/layout/controls_dialog_pin.xml
index 170b32b6c669..d0ef10b649bf 100644
--- a/packages/SystemUI/res/layout/controls_dialog_pin.xml
+++ b/packages/SystemUI/res/layout/controls_dialog_pin.xml
@@ -27,6 +27,7 @@
android:layout_height="wrap_content"
android:minHeight="48dp"
android:longClickable="false"
+ android:textAlignment="viewStart"
android:inputType="numberPassword" />
<CheckBox
android:id="@+id/controls_pin_use_alpha"
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index e22a1660db0c..3a80561e702f 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -24,5 +24,5 @@
<string name="pip_close" msgid="5775212044472849930">"Sulje PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Koko näyttö"</string>
<string name="mic_active" msgid="5766614241012047024">"Mikrofoni aktiivinen"</string>
- <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s sai pääsyn mikrofoniisi"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s käytti mikrofoniasi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index 9b466788d9e0..22580e645ca0 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -24,5 +24,5 @@
<string name="pip_close" msgid="5775212044472849930">"Lukk PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Fullskjerm"</string>
<string name="mic_active" msgid="5766614241012047024">"Mikrofonen er aktiv"</string>
- <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fikk tilgang til mikrofonen din"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s brukte mikrofonen din"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index 852ea5056460..5921aa7a9963 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -24,5 +24,5 @@
<string name="pip_close" msgid="5775212044472849930">"Zamknij PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Pełny ekran"</string>
<string name="mic_active" msgid="5766614241012047024">"Mikrofon aktywny"</string>
- <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacja %1$s uzyskała dostęp do mikrofonu"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacja %1$s korzystała z mikrofonu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index cf40057a005a..64d61621b001 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -24,5 +24,5 @@
<string name="pip_close" msgid="5775212044472849930">"Stäng PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"Helskärm"</string>
<string name="mic_active" msgid="5766614241012047024">"Mikrofonen är aktiv"</string>
- <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s har fått åtkomst till mikrofonen"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s har använt mikrofonen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 1cd63144b904..3cf2b43ed1ff 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -24,5 +24,5 @@
<string name="pip_close" msgid="5775212044472849930">"關閉 PIP"</string>
<string name="pip_fullscreen" msgid="3877997489869475181">"全螢幕"</string>
<string name="mic_active" msgid="5766614241012047024">"麥克風已啟用"</string>
- <string name="app_accessed_mic" msgid="2754428675130470196">"「%1$s」已存取您的麥克風"</string>
+ <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s 曾存取您的麥克風"</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 77ce39fe9953..95de4860ddfa 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2820,6 +2820,8 @@
<string name="controls_media_title">Media</string>
<!-- Explanation for closing controls associated with a specific media session [CHAR_LIMIT=NONE] -->
<string name="controls_media_close_session">Hide the current session.</string>
+ <!-- Explanation that controls associated with a specific media session are active [CHAR_LIMIT=NONE] -->
+ <string name="controls_media_active_session">Current session cannot be hidden.</string>
<!-- Label for a button that will hide media controls [CHAR_LIMIT=30] -->
<string name="controls_media_dismiss_button">Dismiss</string>
<!-- Label for button to resume media playback [CHAR_LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 449ed8c3bcdb..57e656827f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -16,6 +16,7 @@ package com.android.systemui;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.slice.SliceManager;
@@ -29,6 +30,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.text.BidiFormatter;
+import android.util.EventLog;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -50,10 +52,12 @@ public class SlicePermissionActivity extends Activity implements OnClickListener
mUri = getIntent().getParcelableExtra(SliceProvider.EXTRA_BIND_URI);
mCallingPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PKG);
- mProviderPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PROVIDER_PKG);
try {
PackageManager pm = getPackageManager();
+ mProviderPkg = pm.resolveContentProvider(mUri.getAuthority(),
+ PackageManager.GET_META_DATA).applicationInfo.packageName;
+ verifyCallingPkg();
CharSequence app1 = BidiFormatter.getInstance().unicodeWrap(pm.getApplicationInfo(
mCallingPkg, 0).loadSafeLabel(pm, PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
PackageItemInfo.SAFE_LABEL_FLAG_TRIM
@@ -97,4 +101,27 @@ public class SlicePermissionActivity extends Activity implements OnClickListener
public void onDismiss(DialogInterface dialog) {
finish();
}
+
+ private void verifyCallingPkg() {
+ final String providerPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PROVIDER_PKG);
+ if (providerPkg == null || mProviderPkg.equals(providerPkg)) return;
+ final String callingPkg = getCallingPkg();
+ EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg));
+ }
+
+ @Nullable
+ private String getCallingPkg() {
+ final Uri referrer = getReferrer();
+ if (referrer == null) return null;
+ return referrer.getHost();
+ }
+
+ private int getUid(@Nullable final String pkg) {
+ if (pkg == null) return -1;
+ try {
+ return getPackageManager().getApplicationInfo(pkg, 0).uid;
+ } catch (NameNotFoundException e) {
+ }
+ return -1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 5674fdd3bb36..eebf70b7564c 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -18,6 +18,7 @@ package com.android.systemui;
import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
@@ -39,6 +40,7 @@ import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvide
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.phone.BackGestureTfClassifierProvider;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -182,4 +184,13 @@ public class SystemUIFactory {
return mContext;
}
}
+
+ /**
+ * Creates an instance of BackGestureTfClassifierProvider.
+ * This method is overridden in vendor specific implementation of Sys UI.
+ */
+ public BackGestureTfClassifierProvider createBackGestureTfClassifierProvider(
+ AssetManager am, String modelName) {
+ return new BackGestureTfClassifierProvider();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index dbe5a77965be..c1233fe6b9da 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -96,7 +96,7 @@ public class AuthContainerView extends LinearLayout
@VisibleForTesting final WakefulnessLifecycle mWakefulnessLifecycle;
- private @ContainerState int mContainerState = STATE_UNKNOWN;
+ @VisibleForTesting @ContainerState int mContainerState = STATE_UNKNOWN;
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
@Nullable @AuthDialogCallback.DismissedReason Integer mPendingCallbackReason;
@@ -607,10 +607,11 @@ public class AuthContainerView extends LinearLayout
mWindowManager.removeView(this);
}
- private void onDialogAnimatedIn() {
+ @VisibleForTesting
+ void onDialogAnimatedIn() {
if (mContainerState == STATE_PENDING_DISMISS) {
Log.d(TAG, "onDialogAnimatedIn(): mPendingDismissDialog=true, dismissing now");
- animateAway(false /* sendReason */, 0);
+ animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
return;
}
mContainerState = STATE_SHOWING;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 1e556a3ed402..58d5776543a9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -301,7 +301,7 @@ public class BubbleExpandedView extends LinearLayout {
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */, false /* usePublicVirtualDisplay*/,
- true /* disableSurfaceViewBackgroundLayer */);
+ true /* disableSurfaceViewBackgroundLayer */, true /* useTrustedDisplay */);
// Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index aa11df41a7b7..a3a937acec76 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -301,7 +301,7 @@ class ToggleRangeBehavior : Behavior {
}
fun findNearestStep(value: Float): Float {
- var minDiff = 1000f
+ var minDiff = Float.MAX_VALUE
var f = rangeTemplate.getMinValue()
while (f <= rangeTemplate.getMaxValue()) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 810cecca517f..d853e3d4a57c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -359,7 +359,15 @@ public class MediaControlPanel {
final MediaController controller = getController();
mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
+ // Guts label
+ boolean isDismissible = data.isClearable();
+ mViewHolder.getSettingsText().setText(isDismissible
+ ? R.string.controls_media_close_session
+ : R.string.controls_media_active_session);
+
// Dismiss
+ mViewHolder.getDismissLabel().setAlpha(isDismissible ? 1 : DISABLED_ALPHA);
+ mViewHolder.getDismiss().setEnabled(isDismissible);
mViewHolder.getDismiss().setOnClickListener(v -> {
if (mKey != null) {
closeGuts();
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 436d4510aa67..833d08808a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -610,7 +610,8 @@ class MediaDataManager(
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = getResumeMediaAction(removed.resumeAction!!)
val updated = removed.copy(token = null, actions = listOf(resumeAction),
- actionsToShowInCompact = listOf(0), active = false, resumption = true)
+ actionsToShowInCompact = listOf(0), active = false, resumption = true,
+ isClearable = true)
val pkg = removed?.packageName
val migrate = mediaEntries.put(pkg, updated) == null
// Notify listeners of "new" controls when migrating or removed and update when not
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
index dcb7767a680a..63a361de4d87 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
@@ -46,7 +46,7 @@ class MediaTimeoutListener @Inject constructor(
/**
* Callback representing that a media object is now expired:
* @param token Media session unique identifier
- * @param pauseTimeuot True when expired for {@code PAUSED_MEDIA_TIMEOUT}
+ * @param pauseTimeout True when expired for {@code PAUSED_MEDIA_TIMEOUT}
*/
lateinit var timeoutCallback: (String, Boolean) -> Unit
@@ -57,11 +57,10 @@ class MediaTimeoutListener @Inject constructor(
// Having an old key means that we're migrating from/to resumption. We should update
// the old listener to make sure that events will be dispatched to the new location.
val migrating = oldKey != null && key != oldKey
- var wasPlaying = false
if (migrating) {
val reusedListener = mediaListeners.remove(oldKey)
if (reusedListener != null) {
- wasPlaying = reusedListener.playing ?: false
+ val wasPlaying = reusedListener.playing ?: false
if (DEBUG) Log.d(TAG, "migrating key $oldKey to $key, for resumption")
reusedListener.mediaData = data
reusedListener.key = key
@@ -159,9 +158,8 @@ class MediaTimeoutListener @Inject constructor(
Log.v(TAG, "Execute timeout for $key")
}
timedOut = true
- if (dispatchEvents) {
- timeoutCallback(key, timedOut)
- }
+ // this event is async, so it's safe even when `dispatchEvents` is false
+ timeoutCallback(key, timedOut)
}, PAUSED_MEDIA_TIMEOUT)
} else {
expireMediaTimeout(key, "playback started - $state, $key")
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index 666a6038a8b6..16327bd9064a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -60,8 +60,10 @@ class PlayerViewHolder private constructor(itemView: View) {
val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
// Settings screen
+ val settingsText = itemView.requireViewById<TextView>(R.id.remove_text)
val cancel = itemView.requireViewById<View>(R.id.cancel)
- val dismiss = itemView.requireViewById<View>(R.id.dismiss)
+ val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss)
+ val dismissLabel = dismiss.getChildAt(0)
val settings = itemView.requireViewById<View>(R.id.settings)
init {
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
index 9e326aaec3c1..c8244589ce44 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -91,9 +91,9 @@ class SeekBarViewModel @Inject constructor(@Background private val bgExecutor: R
}
private var playbackState: PlaybackState? = null
private var callback = object : MediaController.Callback() {
- override fun onPlaybackStateChanged(state: PlaybackState) {
+ override fun onPlaybackStateChanged(state: PlaybackState?) {
playbackState = state
- if (PlaybackState.STATE_NONE.equals(playbackState)) {
+ if (playbackState == null || PlaybackState.STATE_NONE.equals(playbackState)) {
clearController()
} else {
checkIfPollingNeeded()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 8cd82cc77530..38e1de3cada0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -40,6 +40,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
+import android.service.notification.NotificationListenerService;
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
@@ -52,6 +53,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
@@ -250,6 +252,24 @@ public class NotificationMediaManager implements Dumpable {
}
});
+ mMediaDataManager.addListener(new MediaDataManager.Listener() {
+ @Override
+ public void onMediaDataLoaded(@NonNull String key,
+ @Nullable String oldKey, @NonNull MediaData data) {
+ }
+
+ @Override
+ public void onMediaDataRemoved(@NonNull String key) {
+ NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key);
+ if (entry != null) {
+ // TODO(b/160713608): "removing" this notification won't happen and
+ // won't send the 'deleteIntent' if the notification is ongoing.
+ mEntryManager.performRemoveNotification(entry.getSbn(),
+ NotificationListenerService.REASON_CANCEL);
+ }
+ }
+ });
+
mShowCompactMediaSeekbar = "true".equals(
DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.COMPACT_MEDIA_SEEKBAR_ENABLED));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index d04389d6cbe8..9fd729f425c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -574,6 +574,7 @@ public class NotificationEntryManager implements
NotificationEntry entry = mPendingNotifications.get(key);
if (entry != null) {
entry.setSbn(notification);
+ entry.setRanking(ranking);
} else {
entry = new NotificationEntry(
notification,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index e9cbf32ee052..943ace968632 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -32,8 +32,6 @@ import javax.inject.Singleton;
*/
@Singleton
public class RankingCoordinator implements Coordinator {
- private static final String TAG = "RankingNotificationCoordinator";
-
private final StatusBarStateController mStatusBarStateController;
@Inject
@@ -46,7 +44,7 @@ public class RankingCoordinator implements Coordinator {
mStatusBarStateController.addCallback(mStatusBarStateCallback);
pipeline.addPreGroupFilter(mSuspendedFilter);
- pipeline.addPreGroupFilter(mDozingFilter);
+ pipeline.addPreGroupFilter(mDndVisualEffectsFilter);
}
/**
@@ -61,10 +59,10 @@ public class RankingCoordinator implements Coordinator {
}
};
- private final NotifFilter mDozingFilter = new NotifFilter("IsDozingFilter") {
+ private final NotifFilter mDndVisualEffectsFilter = new NotifFilter(
+ "DndSuppressingVisualEffects") {
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
- // Dozing + DND Settings from Ranking object
if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) {
return true;
}
@@ -77,7 +75,7 @@ public class RankingCoordinator implements Coordinator {
new StatusBarStateController.StateListener() {
@Override
public void onDozingChanged(boolean isDozing) {
- mDozingFilter.invalidateList();
+ mDndVisualEffectsFilter.invalidateList();
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 94e12e82f850..70dd80e71e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -504,7 +504,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
/**
* Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
- * or is in a whitelist).
+ * or is in an allowList).
*/
public boolean getIsNonblockable() {
boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackGestureTfClassifierProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackGestureTfClassifierProvider.java
new file mode 100644
index 000000000000..0af79c3886b9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BackGestureTfClassifierProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone;
+
+import android.content.res.AssetManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class can be overridden by a vendor-specific sys UI implementation,
+ * in order to provide classification models for the Back Gesture.
+ */
+public class BackGestureTfClassifierProvider {
+ private static final String TAG = "BackGestureTfClassifierProvider";
+
+ /**
+ * Default implementation that returns an empty map.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param am An AssetManager to get the vocab file.
+ */
+ public Map<String, Integer> loadVocab(AssetManager am) {
+ return new HashMap<String, Integer>();
+ }
+
+ /**
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param featuresVector List of input features.
+ *
+ */
+ public float predict(Object[] featuresVector) {
+ return -1;
+ }
+
+ /**
+ * Interpreter owns resources. This method releases the resources after
+ * use to avoid memory leak.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ */
+ public void release() {}
+
+ /**
+ * Returns whether to use the ML model for Back Gesture.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ */
+ public boolean isActive() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 00a932cb1e8a..dc42997be0d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -56,6 +56,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.model.SysUiState;
@@ -76,6 +77,7 @@ import com.android.systemui.tracing.nano.SystemUiTraceProto;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Executor;
/**
@@ -117,8 +119,33 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
public void onTaskStackChanged() {
mGestureBlockingActivityRunning = isGestureBlockingActivityRunning();
}
+ @Override
+ public void onTaskCreated(int taskId, ComponentName componentName) {
+ if (componentName != null) {
+ mPackageName = componentName.getPackageName();
+ } else {
+ mPackageName = "_UNKNOWN";
+ }
+ }
};
+ private DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ if (DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())
+ && (properties.getKeyset().contains(
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD)
+ || properties.getKeyset().contains(
+ SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL)
+ || properties.getKeyset().contains(
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME))) {
+ updateMLModelState();
+ }
+ }
+ };
+
+
private final Context mContext;
private final OverviewProxyService mOverviewProxyService;
private final Runnable mStateChangeCallback;
@@ -173,6 +200,14 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
private int mRightInset;
private int mSysUiFlags;
+ // For Tf-Lite model.
+ private BackGestureTfClassifierProvider mBackGestureTfClassifierProvider;
+ private Map<String, Integer> mVocab;
+ private boolean mUseMLModel;
+ private float mMLModelThreshold;
+ private String mPackageName;
+ private float mMLResults;
+
private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
private final NavigationEdgeBackPlugin.BackCallback mBackCallback =
@@ -230,7 +265,6 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
Log.e(TAG, "Failed to add gesture blocking activities", e);
}
}
-
mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
ViewConfiguration.getLongPressTimeout());
@@ -344,6 +378,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
mPluginManager.removePluginListener(this);
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
+ DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -359,6 +394,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
mContext.getMainThreadHandler());
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+ runnable -> (mContext.getMainThreadHandler()).post(runnable),
+ mOnPropertiesChangedListener);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -379,6 +417,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
mPluginManager.addPluginListener(
this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
}
+ // Update the ML model resources.
+ updateMLModelState();
}
@Override
@@ -431,12 +471,72 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
}
}
+ private void updateMLModelState() {
+ boolean newState = mIsEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
+
+ if (newState == mUseMLModel) {
+ return;
+ }
+
+ if (newState) {
+ String mlModelName = DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME, "backgesture");
+ mBackGestureTfClassifierProvider = SystemUIFactory.getInstance()
+ .createBackGestureTfClassifierProvider(mContext.getAssets(), mlModelName);
+ mMLModelThreshold = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD, 0.9f);
+ if (mBackGestureTfClassifierProvider.isActive()) {
+ mVocab = mBackGestureTfClassifierProvider.loadVocab(mContext.getAssets());
+ mUseMLModel = true;
+ return;
+ }
+ }
+
+ mUseMLModel = false;
+ if (mBackGestureTfClassifierProvider != null) {
+ mBackGestureTfClassifierProvider.release();
+ mBackGestureTfClassifierProvider = null;
+ }
+ }
+
+ private float getBackGesturePredictionsCategory(int x, int y) {
+ if (!mVocab.containsKey(mPackageName)) {
+ return -1;
+ }
+
+ int distanceFromEdge;
+ int location;
+ if (x <= mDisplaySize.x / 2.0) {
+ location = 1; // left
+ distanceFromEdge = x;
+ } else {
+ location = 2; // right
+ distanceFromEdge = mDisplaySize.x - x;
+ }
+
+ Object[] featuresVector = {
+ new long[]{(long) mDisplaySize.x},
+ new long[]{(long) distanceFromEdge},
+ new long[]{(long) location},
+ new long[]{(long) mVocab.get(mPackageName)},
+ new long[]{(long) y},
+ };
+
+ mMLResults = mBackGestureTfClassifierProvider.predict(featuresVector);
+ if (mMLResults == -1) return -1;
+
+ return mMLResults >= mMLModelThreshold ? 1 : 0;
+ }
+
private boolean isWithinTouchRegion(int x, int y) {
+ boolean withinRange = false;
+ float results = -1;
+
// Disallow if we are in the bottom gesture area
if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
return false;
}
-
// If the point is way too far (twice the margin), it is
// not interesting to us for logging purposes, nor we
// should process it. Simply return false and keep
@@ -446,11 +546,15 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
return false;
}
- // Denotes whether we should proceed with the gesture.
- // Even if it is false, we may want to log it assuming
- // it is not invalid due to exclusion.
- boolean withinRange = x <= mEdgeWidthLeft + mLeftInset
- || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset);
+ if (mUseMLModel && (results = getBackGesturePredictionsCategory(x, y)) != -1) {
+ withinRange = results == 1 ? true : false;
+ } else {
+ // Denotes whether we should proceed with the gesture.
+ // Even if it is false, we may want to log it assuming
+ // it is not invalid due to exclusion.
+ withinRange = x <= mEdgeWidthLeft + mLeftInset
+ || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset);
+ }
// Always allow if the user is in a transient sticky immersive state
if (mIsNavBarShownTransiently) {
@@ -493,6 +597,11 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
return;
}
mLogGesture = false;
+ String logPackageName = "";
+ // Due to privacy, only top 100 most used apps by all users can be logged.
+ if (mUseMLModel && mVocab.containsKey(mPackageName) && mVocab.get(mPackageName) < 100) {
+ logPackageName = mPackageName;
+ }
SysUiStatsLog.write(SysUiStatsLog.BACK_GESTURE_REPORTED_REPORTED, backType,
(int) mDownPoint.y, mIsOnLeftEdge
? SysUiStatsLog.BACK_GESTURE__X_LOCATION__LEFT
@@ -500,7 +609,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
(int) mDownPoint.x, (int) mDownPoint.y,
(int) mEndPoint.x, (int) mEndPoint.y,
mEdgeWidthLeft + mLeftInset,
- mDisplaySize.x - (mEdgeWidthRight + mRightInset));
+ mDisplaySize.x - (mEdgeWidthRight + mRightInset),
+ mUseMLModel ? mMLResults : -2, logPackageName);
}
private void onMotionEvent(MotionEvent ev) {
@@ -509,6 +619,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
// Verify if this is in within the touch region and we aren't in immersive mode, and
// either the bouncer is showing or the notification panel is hidden
mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
+ mMLResults = 0;
mLogGesture = false;
mInRejectedExclusion = false;
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
@@ -648,6 +759,11 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
ActivityManager.RunningTaskInfo runningTask =
ActivityManagerWrapper.getInstance().getRunningTask();
ComponentName topActivity = runningTask == null ? null : runningTask.topActivity;
+ if (topActivity != null) {
+ mPackageName = topActivity.getPackageName();
+ } else {
+ mPackageName = "_UNKNOWN";
+ }
return topActivity != null && mGestureBlockingActivities.contains(topActivity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 286b7c049fc7..21d700e41a40 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -35,6 +35,8 @@ import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
@@ -58,6 +60,9 @@ public class UsbConfirmActivity extends AlertActivity
@Override
public void onCreate(Bundle icicle) {
+ getWindow().addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
super.onCreate(icicle);
Intent intent = getIntent();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 29d7a524dd8b..5f3f3a79e31d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -204,6 +204,16 @@ public class AuthContainerViewTest extends SysuiTestCase {
}
@Test
+ public void testOnDialogAnimatedIn_sendsCancelReason_whenPendingDismiss() {
+ initializeContainer(Authenticators.BIOMETRIC_WEAK);
+ mAuthContainer.mContainerState = AuthContainerView.STATE_PENDING_DISMISS;
+ mAuthContainer.onDialogAnimatedIn();
+ verify(mCallback).onDismissed(
+ eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
+ eq(null) /* credentialAttestation */);
+ }
+
+ @Test
public void testLayoutParams_hasSecureWindowFlag() {
final IBinder windowToken = mock(IBinder.class);
final WindowManager.LayoutParams layoutParams =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ToggleRangeTemplateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ToggleRangeTemplateTest.kt
new file mode 100644
index 000000000000..31e09549a2b5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ToggleRangeTemplateTest.kt
@@ -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.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.service.controls.templates.RangeTemplate
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ToggleRangeTemplateTest : SysuiTestCase() {
+
+ @Test
+ fun testLargeRangeNearestStep() {
+ val trt = ToggleRangeBehavior()
+ trt.rangeTemplate = RangeTemplate("range", -100000f, 100000f, 0f, 5f, null)
+
+ assertEquals(255f, trt.findNearestStep(253f), 0.1f)
+ }
+
+ @Test
+ fun testLargeRangeNearestStepWithNegativeValues() {
+ val trt = ToggleRangeBehavior()
+ trt.rangeTemplate = RangeTemplate("range", -100000f, 100000f, 0f, 5f, null)
+
+ assertEquals(-7855f, trt.findNearestStep(-7853.2f), 0.1f)
+ }
+
+ @Test
+ fun testFractionalRangeNearestStep() {
+ val trt = ToggleRangeBehavior()
+ trt.rangeTemplate = RangeTemplate("range", 10f, 11f, 10f, .01f, null)
+
+ assertEquals(10.54f, trt.findNearestStep(10.543f), 0.01f)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 81139f192070..ad703614fdb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -109,9 +109,11 @@ public class MediaControlPanelTest : SysuiTestCase() {
private lateinit var action2: ImageButton
private lateinit var action3: ImageButton
private lateinit var action4: ImageButton
+ private lateinit var settingsText: TextView
private lateinit var settings: View
private lateinit var cancel: View
- private lateinit var dismiss: View
+ private lateinit var dismiss: FrameLayout
+ private lateinit var dismissLabel: View
private lateinit var session: MediaSession
private val device = MediaDeviceData(true, null, DEVICE_NAME)
@@ -168,12 +170,16 @@ public class MediaControlPanelTest : SysuiTestCase() {
whenever(holder.action3).thenReturn(action3)
action4 = ImageButton(context)
whenever(holder.action4).thenReturn(action4)
+ settingsText = TextView(context)
+ whenever(holder.settingsText).thenReturn(settingsText)
settings = View(context)
whenever(holder.settings).thenReturn(settings)
cancel = View(context)
whenever(holder.cancel).thenReturn(cancel)
- dismiss = View(context)
+ dismiss = FrameLayout(context)
whenever(holder.dismiss).thenReturn(dismiss)
+ dismissLabel = View(context)
+ whenever(holder.dismissLabel).thenReturn(dismissLabel)
// Create media session
val metadataBuilder = MediaMetadata.Builder().apply {
@@ -327,6 +333,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
notificationKey = KEY)
player.bind(state, mediaKey)
+ assertThat(dismiss.isEnabled).isEqualTo(true)
dismiss.callOnClick()
val captor = ArgumentCaptor.forClass(ActivityStarter.OnDismissAction::class.java)
verify(keyguardDismissUtil).executeWhenUnlocked(captor.capture(), anyBoolean())
@@ -334,4 +341,16 @@ public class MediaControlPanelTest : SysuiTestCase() {
captor.value.onDismiss()
verify(mediaDataManager).dismissMediaData(eq(mediaKey), anyLong())
}
+
+ @Test
+ fun dismissButtonDisabled() {
+ val mediaKey = "key for dismissal"
+ player.attach(holder)
+ val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+ emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null,
+ isClearable = false, notificationKey = KEY)
+ player.bind(state, mediaKey)
+
+ assertThat(dismiss.isEnabled).isEqualTo(false)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
index b81ab74458ce..1f9862c07a4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -654,4 +654,21 @@ public class SeekBarViewModelTest : SysuiTestCase() {
fakeExecutor.runAllReady()
verify(mockController).unregisterCallback(any())
}
+
+ @Test
+ fun nullPlaybackStateUnregistersCallback() {
+ viewModel.updateController(mockController)
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(mockController).registerCallback(captor.capture())
+ val callback = captor.value
+ // WHEN the callback receives a null state
+ callback.onPlaybackStateChanged(null)
+ with(fakeExecutor) {
+ advanceClockToNext()
+ runAllReady()
+ }
+ // THEN we unregister callback (as a result of clearing the controller)
+ fakeExecutor.runAllReady()
+ verify(mockController).unregisterCallback(any())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 90423c18216a..f1e6bf604a14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -382,6 +382,36 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
}
@Test
+ public void testUpdatePendingNotification_rankingUpdated() {
+ // GIVEN a notification with ranking is pending
+ final Ranking originalRanking = mEntry.getRanking();
+ mEntryManager.mPendingNotifications.put(mEntry.getKey(), mEntry);
+
+ // WHEN the same notification has been updated with a new ranking
+ final int newRank = 2345;
+ doAnswer(invocationOnMock -> {
+ Ranking ranking = (Ranking)
+ invocationOnMock.getArguments()[1];
+ ranking.populate(
+ mEntry.getKey(),
+ newRank, /* this changed!! */
+ false,
+ 0,
+ 0,
+ IMPORTANCE_DEFAULT,
+ null, null,
+ null, null, null, true,
+ Ranking.USER_SENTIMENT_NEUTRAL, false, -1,
+ false, null, null, false, false, false, null, false);
+ return true;
+ }).when(mRankingMap).getRanking(eq(mEntry.getKey()), any(Ranking.class));
+ mEntryManager.addNotification(mSbn, mRankingMap);
+
+ // THEN ranking for the entry has been updated with new ranking
+ assertEquals(newRank, mEntry.getRanking().getRank());
+ }
+
+ @Test
public void testLifetimeExtenders_ifNotificationIsRetainedItIsntRemoved() {
// GIVEN an entry manager with a notification
mEntryManager.addActiveNotificationForTest(mEntry);
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
new file mode 100644
index 000000000000..035455df11bb
--- /dev/null
+++ b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_bluetooth_transient_animation.xml
@@ -0,0 +1,219 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M6.5 12 C6.5,11.17 5.83,10.5 5,10.5 C4.17,10.5 3.5,11.17 3.5,12 C3.5,12.83 4.17,13.5 5,13.5 C5.83,13.5 6.5,12.83 6.5,12c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M19 10.5 C18.17,10.5 17.5,11.17 17.5,12 C17.5,12.83 18.17,13.5 19,13.5 C19.83,13.5 20.5,12.83 20.5,12 C20.5,11.17 19.83,10.5 19,10.5c " />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:pathData=" M6.49 5.98 C6.49,5.98 17.25,16.74 17.25,16.74 C17.25,16.74 17.25,17.28 17.25,17.28 C17.25,17.28 13.3,21.23 13.3,21.23 C13.3,21.23 12.5,21.23 12.5,21.23 C12.5,21.23 12.5,2.75 12.5,2.75 C12.5,2.75 13.3,2.75 13.3,2.75 C13.3,2.75 17.25,6.7 17.25,6.7 C17.25,6.7 17.25,7.24 17.25,7.24 C17.25,7.24 6.49,18 6.49,18 "
+ android:strokeWidth="1.5"
+ android:strokeAlpha="1"
+ android:strokeColor="#000000" />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="fillAlpha"
+ android:startOffset="17"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="250"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="fillAlpha"
+ android:startOffset="267"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="500"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="fillAlpha"
+ android:startOffset="517"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="750"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="250"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="250"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="fillAlpha"
+ android:startOffset="267"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="500"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="fillAlpha"
+ android:startOffset="517"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="750"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="1017"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
new file mode 100644
index 000000000000..235e67f31974
--- /dev/null
+++ b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_hotspot_transient_animation.xml
@@ -0,0 +1,204 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_0_G">
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:pathData=" M12 11 C10.9,11 10,11.9 10,13 C10,14.1 10.9,15 12,15 C13.1,15 14,14.1 14,13 C14,11.9 13.1,11 12,11c " />
+ <path
+ android:name="_R_G_L_0_G_D_1_P_0"
+ android:pathData=" M8.29 16.71 C7.34,15.76 6.75,14.45 6.75,13 C6.75,10.1 9.1,7.75 12,7.75 C14.9,7.75 17.25,10.1 17.25,13 C17.25,14.45 16.66,15.76 15.71,16.71 "
+ android:strokeWidth="1.5"
+ android:strokeAlpha="1"
+ android:strokeColor="#000000"
+ />
+ <path
+ android:name="_R_G_L_0_G_D_2_P_0"
+ android:pathData=" M5.46 19.54 C3.79,17.87 2.75,15.56 2.75,13 C2.75,7.89 6.89,3.75 12,3.75 C17.11,3.75 21.25,7.89 21.25,13 C21.25,15.56 20.21,17.87 18.54,19.54 "
+ android:strokeWidth="1.5"
+ android:strokeAlpha="1"
+ android:strokeColor="#000000" />
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_0_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="583"
+ android:propertyName="fillAlpha"
+ android:startOffset="17"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="fillAlpha"
+ android:startOffset="600"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_1_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:startOffset="200"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="583"
+ android:propertyName="strokeAlpha"
+ android:startOffset="217"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:startOffset="800"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_D_2_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="strokeAlpha"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:startOffset="400"
+ android:valueFrom="1"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="583"
+ android:propertyName="strokeAlpha"
+ android:startOffset="417"
+ android:valueFrom="0.5"
+ android:valueTo="0.5"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="17"
+ android:propertyName="strokeAlpha"
+ android:startOffset="1000"
+ android:valueFrom="0.5"
+ android:valueTo="1"
+ android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator
+ android:duration="1250"
+ android:propertyName="translateX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
new file mode 100644
index 000000000000..b988fdf67191
--- /dev/null
+++ b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_signal_wifi_transient_animation.xml
@@ -0,0 +1,18 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="24dp" android:width="24dp" android:viewportHeight="24" android:viewportWidth="24"><group android:name="_R_G"><group android:name="_R_G_L_1_G"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M12 2 C7.76,2 3.89,3.67 1,6.38 C1,6.38 1,8.61 1,8.61 C1,8.61 11,21 11,21 C11,21 13,21 13,21 C13,21 23,8.61 23,8.61 C23,8.61 23,6.38 23,6.38 C20.11,3.67 16.24,2 12,2c M12 19.85 C12,19.85 2.02,7.49 2.02,7.49 C4.78,4.91 8.28,3.5 12,3.5 C15.73,3.5 19.23,4.91 21.98,7.49 C21.98,7.49 12,19.85 12,19.85c "/><path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#000000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M12 13 C9.9,13 7.9,13.9 6.6,15.4 C6.6,15.4 12,21 12,21 C12,21 17.4,15.4 17.4,15.4 C16.1,13.9 14.1,13 12,13c "/><path android:name="_R_G_L_1_G_D_2_P_0" android:fillColor="#000000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M12 10 C9.2,10 6.5,11.2 4.8,13.2 C4.8,13.2 12,21 12,21 C12,21 19.2,13.2 19.2,13.2 C17.5,11.2 14.8,10 12,10c "/><path android:name="_R_G_L_1_G_D_3_P_0" android:fillColor="#000000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M12 7 C8.5,7 5.2,8.5 3,11 C3,11 12,21 12,21 C12,21 21,11 21,11 C18.8,8.5 15.5,7 12,7c "/><path android:name="_R_G_L_1_G_D_4_P_0" android:fillColor="#000000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M12 2 C7.76,2 3.89,3.67 1,6.38 C1,6.38 1,8.61 1,8.61 C1,8.61 11,21 11,21 C11,21 13,21 13,21 C13,21 23,8.61 23,8.61 C23,8.61 23,6.38 23,6.38 C20.11,3.67 16.24,2 12,2c "/></group><group android:name="_R_G_L_0_G"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M12 2 C7.76,2 3.89,3.67 1,6.38 C1,6.38 1,8.61 1,8.61 C1,8.61 11,21 11,21 C11,21 13,21 13,21 C13,21 23,8.61 23,8.61 C23,8.61 23,6.38 23,6.38 C20.11,3.67 16.24,2 12,2c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="150" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="17" android:startOffset="150" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_2_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="317" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="17" android:startOffset="317" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_3_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="483" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="17" android:startOffset="483" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="667" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="650" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="17" android:startOffset="650" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="0" android:startOffset="600" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="850" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_work_apps_off.xml b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_work_apps_off.xml
new file mode 100644
index 000000000000..22540e2dee15
--- /dev/null
+++ b/packages/overlays/IconPackVictorAndroidOverlay/res/drawable/ic_work_apps_off.xml
@@ -0,0 +1,19 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector android:height="32dp" android:viewportHeight="24" android:viewportWidth="24" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M19.5,19.5l-6-6L12,12L7.5,7.5L6,6L2.81,2.81L1.75,3.87L3.88,6H3.41L2,7.41v12.17L3.41,21h15.46l1.25,1.25l1.06-1.06 l-0.4-0.4L19.5,19.5z M3.5,19.5v-12h1.88l5.3,5.3c-0.11,0.21-0.18,0.44-0.18,0.7c0,0.83,0.67,1.5,1.5,1.5 c0.25,0,0.49-0.07,0.7-0.18l4.68,4.68H3.5z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M9.62,7.5H20.5v10.88l1.35,1.35L22,19.59V7.41L20.59,6H16V3.41L14.59,2H9.41L8,3.41v2.46L9.62,7.5z M9.5,3.5h5V6h-5V3.5z"/>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconShapePebbleOverlay/res/values/config.xml b/packages/overlays/IconShapePebbleOverlay/res/values/config.xml
index 2465fe015538..e7eeb30501b5 100644
--- a/packages/overlays/IconShapePebbleOverlay/res/values/config.xml
+++ b/packages/overlays/IconShapePebbleOverlay/res/values/config.xml
@@ -18,7 +18,7 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
- <string name="config_icon_mask" translatable="false">"MM55,0 C25,0 0,25 0,50 0,78 28,100 55,100 85,100 100,85 100,58 100,30 86,0 55,0 Z"</string>
+ <string name="config_icon_mask" translatable="false">"M55,0 C25,0 0,25 0,50 0,78 28,100 55,100 85,100 100,85 100,58 100,30 86,0 55,0 Z"</string>
<!-- Flag indicating whether round icons should be parsed from the application manifest. -->
<bool name="config_useRoundIcon">false</bool>
<!-- Corner radius of system dialogs -->
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 40a2816ee7de..8822d55cc30f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -148,6 +148,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
private boolean mRequestMultiFingerGestures;
+ private boolean mRequestTwoFingerPassthrough;
+
boolean mRequestFilterKeyEvents;
boolean mRetrieveInteractiveWindows;
@@ -323,8 +325,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
& AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0;
mRequestMultiFingerGestures = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
- mRequestFilterKeyEvents = (info.flags
- & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
+ mRequestTwoFingerPassthrough =
+ (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0;
+ mRequestFilterKeyEvents =
+ (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
mRetrieveInteractiveWindows = (info.flags
& AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
mCaptureFingerprintGestures = (info.flags
@@ -1773,6 +1777,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
return mRequestMultiFingerGestures;
}
+ public boolean isTwoFingerPassthroughEnabled() {
+ return mRequestTwoFingerPassthrough;
+ }
+
@Override
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 020f2253743d..a04a7c570b5c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -114,6 +114,13 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
*/
static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000100;
+ /**
+ * Flag for enabling multi-finger gestures.
+ *
+ * @see #setUserAndEnabledFeatures(int, int)
+ */
+ static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x00000200;
+
static final int FEATURES_AFFECTING_MOTION_EVENTS =
FLAG_FEATURE_INJECT_MOTION_EVENTS
| FLAG_FEATURE_AUTOCLICK
@@ -121,7 +128,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
| FLAG_FEATURE_SCREEN_MAGNIFIER
| FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER
| FLAG_SERVICE_HANDLES_DOUBLE_TAP
- | FLAG_REQUEST_MULTI_FINGER_GESTURES;
+ | FLAG_REQUEST_MULTI_FINGER_GESTURES
+ | FLAG_REQUEST_2_FINGER_PASSTHROUGH;
private final Context mContext;
@@ -417,6 +425,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
if ((mEnabledFeatures & FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0) {
explorer.setMultiFingerGesturesEnabled(true);
}
+ if ((mEnabledFeatures & FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0) {
+ explorer.setTwoFingerPassthroughEnabled(true);
+ }
addFirstEventHandler(displayId, explorer);
mTouchExplorer.put(displayId, explorer);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index fcf270b4ef35..9c10bad1775a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1742,6 +1742,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (userState.isMultiFingerGesturesEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_REQUEST_MULTI_FINGER_GESTURES;
}
+ if (userState.isTwoFingerPassthroughEnabledLocked()) {
+ flags |= AccessibilityInputFilter.FLAG_REQUEST_2_FINGER_PASSTHROUGH;
+ }
}
if (userState.isFilterKeyEventsEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
@@ -2020,6 +2023,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
boolean touchExplorationEnabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
boolean serviceHandlesDoubleTapEnabled = false;
boolean requestMultiFingerGestures = false;
+ boolean requestTwoFingerPassthrough = false;
final int serviceCount = userState.mBoundServices.size();
for (int i = 0; i < serviceCount; i++) {
AccessibilityServiceConnection service = userState.mBoundServices.get(i);
@@ -2027,6 +2031,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
touchExplorationEnabled = true;
serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled();
requestMultiFingerGestures = service.isMultiFingerGesturesEnabled();
+ requestTwoFingerPassthrough = service.isTwoFingerPassthroughEnabled();
break;
}
}
@@ -2043,6 +2048,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
+ userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough);
}
private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 0845d019c060..299a776df1d0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -109,6 +109,7 @@ class AccessibilityUserState {
private boolean mIsTouchExplorationEnabled;
private boolean mServiceHandlesDoubleTap;
private boolean mRequestMultiFingerGestures;
+ private boolean mRequestTwoFingerPassthrough;
private int mUserInteractiveUiTimeout;
private int mUserNonInteractiveUiTimeout;
private int mNonInteractiveUiTimeout = 0;
@@ -160,6 +161,7 @@ class AccessibilityUserState {
mIsTouchExplorationEnabled = false;
mServiceHandlesDoubleTap = false;
mRequestMultiFingerGestures = false;
+ mRequestTwoFingerPassthrough = false;
mIsDisplayMagnificationEnabled = false;
mIsAutoclickEnabled = false;
mUserNonInteractiveUiTimeout = 0;
@@ -446,6 +448,8 @@ class AccessibilityUserState {
.append(String.valueOf(mServiceHandlesDoubleTap));
pw.append(", requestMultiFingerGestures=")
.append(String.valueOf(mRequestMultiFingerGestures));
+ pw.append(", requestTwoFingerPassthrough=")
+ .append(String.valueOf(mRequestTwoFingerPassthrough));
pw.append(", displayMagnificationEnabled=").append(String.valueOf(
mIsDisplayMagnificationEnabled));
pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
@@ -733,6 +737,14 @@ class AccessibilityUserState {
public void setMultiFingerGesturesLocked(boolean enabled) {
mRequestMultiFingerGestures = enabled;
}
+ public boolean isTwoFingerPassthroughEnabledLocked() {
+ return mRequestTwoFingerPassthrough;
+ }
+
+ public void setTwoFingerPassthroughLocked(boolean enabled) {
+ mRequestTwoFingerPassthrough = enabled;
+ }
+
public int getUserInteractiveUiTimeoutLocked() {
return mUserInteractiveUiTimeout;
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
index 070626be9f80..a4fec82bcf56 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
@@ -256,6 +256,7 @@ class EventDispatcher {
return actionMasked;
}
}
+
/**
* Sends down events to the view hierarchy for all pointers which are not already being
* delivered i.e. pointers that are not yet injected.
@@ -285,6 +286,79 @@ class EventDispatcher {
}
/**
+ * Sends down events to the view hierarchy for all pointers which are not already being
+ * delivered with original down location. i.e. pointers that are not yet injected. The down time
+ * is also replaced by the original one.
+ *
+ *
+ * @param prototype The prototype from which to create the injected events.
+ * @param policyFlags The policy flags associated with the event.
+ */
+ void sendDownForAllNotInjectedPointersWithOriginalDown(MotionEvent prototype, int policyFlags) {
+ // Inject the injected pointers.
+ int pointerIdBits = 0;
+ final int pointerCount = prototype.getPointerCount();
+ final MotionEvent event = computeEventWithOriginalDown(prototype);
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = prototype.getPointerId(i);
+ // Do not send event for already delivered pointers.
+ if (!mState.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(
+ event,
+ action,
+ mState.getLastReceivedEvent(),
+ pointerIdBits,
+ policyFlags);
+ }
+ }
+ }
+
+ private MotionEvent computeEventWithOriginalDown(MotionEvent prototype) {
+ final int pointerCount = prototype.getPointerCount();
+ if (pointerCount != mState.getReceivedPointerTracker().getReceivedPointerDownCount()) {
+ Slog.w(LOG_TAG, "The pointer count doesn't match the received count.");
+ return MotionEvent.obtain(prototype);
+ }
+ MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointerCount];
+ MotionEvent.PointerProperties[] properties =
+ new MotionEvent.PointerProperties[pointerCount];
+ for (int i = 0; i < pointerCount; ++i) {
+ final int pointerId = prototype.getPointerId(i);
+ final float x = mState.getReceivedPointerTracker().getReceivedPointerDownX(pointerId);
+ final float y = mState.getReceivedPointerTracker().getReceivedPointerDownY(pointerId);
+ coords[i] = new MotionEvent.PointerCoords();
+ coords[i].x = x;
+ coords[i].y = y;
+ properties[i] = new MotionEvent.PointerProperties();
+ properties[i].id = pointerId;
+ properties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;
+ }
+ MotionEvent event =
+ MotionEvent.obtain(
+ prototype.getDownTime(),
+ // The event time is used for downTime while sending ACTION_DOWN. We adjust
+ // it to avoid the motion velocity is too fast in the beginning after
+ // Delegating.
+ prototype.getDownTime(),
+ prototype.getAction(),
+ pointerCount,
+ properties,
+ coords,
+ prototype.getMetaState(),
+ prototype.getButtonState(),
+ prototype.getXPrecision(),
+ prototype.getYPrecision(),
+ prototype.getDeviceId(),
+ prototype.getEdgeFlags(),
+ prototype.getSource(),
+ prototype.getFlags());
+ return event;
+ }
+
+ /**
+ *
* Sends up events to the view hierarchy for all pointers which are already being delivered i.e.
* pointers that are injected.
*
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 5c15214284f0..7f07c2878088 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -94,17 +94,23 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
private boolean mServiceHandlesDoubleTap = false;
// Whether multi-finger gestures are enabled.
boolean mMultiFingerGesturesEnabled;
+ // Whether the two-finger passthrough is enabled when multi-finger gestures are enabled.
+ private boolean mTwoFingerPassthroughEnabled;
// A list of all the multi-finger gestures, for easy adding and removal.
private final List<GestureMatcher> mMultiFingerGestures = new ArrayList<>();
+ // A list of two-finger swipes, for easy adding and removal when turning on or off two-finger
+ // passthrough.
+ private final List<GestureMatcher> mTwoFingerSwipes = new ArrayList<>();
// Shared state information.
private TouchState mState;
- GestureManifold(Context context, Listener listener, TouchState state) {
+ GestureManifold(Context context, Listener listener, TouchState state, Handler handler) {
mContext = context;
- mHandler = new Handler(context.getMainLooper());
+ mHandler = handler;
mListener = listener;
mState = state;
mMultiFingerGesturesEnabled = false;
+ mTwoFingerPassthroughEnabled = false;
// Set up gestures.
// Start with double tap.
mGestures.add(new MultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
@@ -161,14 +167,14 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
mMultiFingerGestures.add(
new MultiFingerMultiTap(mContext, 4, 3, GESTURE_4_FINGER_TRIPLE_TAP, this));
// Two-finger swipes.
- mMultiFingerGestures.add(
+ mTwoFingerSwipes.add(
new MultiFingerSwipe(context, 2, DOWN, GESTURE_2_FINGER_SWIPE_DOWN, this));
- mMultiFingerGestures.add(
+ mTwoFingerSwipes.add(
new MultiFingerSwipe(context, 2, LEFT, GESTURE_2_FINGER_SWIPE_LEFT, this));
- mMultiFingerGestures.add(
+ mTwoFingerSwipes.add(
new MultiFingerSwipe(context, 2, RIGHT, GESTURE_2_FINGER_SWIPE_RIGHT, this));
- mMultiFingerGestures.add(
- new MultiFingerSwipe(context, 2, UP, GESTURE_2_FINGER_SWIPE_UP, this));
+ mTwoFingerSwipes.add(new MultiFingerSwipe(context, 2, UP, GESTURE_2_FINGER_SWIPE_UP, this));
+ mMultiFingerGestures.addAll(mTwoFingerSwipes);
// Three-finger swipes.
mMultiFingerGestures.add(
new MultiFingerSwipe(context, 3, DOWN, GESTURE_3_FINGER_SWIPE_DOWN, this));
@@ -360,6 +366,25 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
}
}
+ public boolean isTwoFingerPassthroughEnabled() {
+ return mTwoFingerPassthroughEnabled;
+ }
+
+ public void setTwoFingerPassthroughEnabled(boolean mode) {
+ if (mTwoFingerPassthroughEnabled != mode) {
+ mTwoFingerPassthroughEnabled = mode;
+ if (!mode) {
+ mMultiFingerGestures.addAll(mTwoFingerSwipes);
+ if (mMultiFingerGesturesEnabled) {
+ mGestures.addAll(mTwoFingerSwipes);
+ }
+ } else {
+ mMultiFingerGestures.removeAll(mTwoFingerSwipes);
+ mGestures.removeAll(mTwoFingerSwipes);
+ }
+ }
+ }
+
public void setServiceHandlesDoubleTap(boolean mode) {
mServiceHandlesDoubleTap = mode;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
index 4b89731b75b6..2a305397924f 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
@@ -294,7 +294,7 @@ class MultiFingerSwipe extends GestureMatcher {
+ Float.toString(mGestureDetectionThresholdPixels));
}
if (getState() == STATE_CLEAR) {
- if (moveDelta < mTouchSlop) {
+ if (moveDelta < (mTargetFingerCount * mTouchSlop)) {
// This still counts as a touch not a swipe.
continue;
} else if (mStrokeBuffers[pointerIndex].size() == 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 6074ac94faf3..b6126d741718 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -24,6 +24,7 @@ import android.accessibilityservice.AccessibilityGestureEvent;
import android.content.Context;
import android.graphics.Region;
import android.os.Handler;
+import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -73,12 +74,21 @@ public class TouchExplorer extends BaseEventStreamTransformation
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
+ // The height of the top and bottom edges for edge-swipes.
+ // For now this is only used to allow three-finger edge-swipes from the bottom.
+ private static final float EDGE_SWIPE_HEIGHT_CM = 0.25f;
+
+ // The calculated edge height for the top and bottom edges.
+ private final float mEdgeSwipeHeightPixels;
// Timeout before trying to decide what the user is trying to do.
private final int mDetermineUserIntentTimeout;
// Slop between the first and second tap to be a double tap.
private final int mDoubleTapSlop;
+ // Slop to move before being considered a move rather than a tap.
+ private final int mTouchSlop;
+
// The current state of the touch explorer.
private TouchState mState;
@@ -151,6 +161,9 @@ public class TouchExplorer extends BaseEventStreamTransformation
mDispatcher = new EventDispatcher(context, mAms, super.getNext(), mState);
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
+ mEdgeSwipeHeightPixels = metrics.ydpi / GestureUtils.CM_PER_INCH * EDGE_SWIPE_HEIGHT_CM;
mHandler = new Handler(context.getMainLooper());
mExitGestureDetectionModeDelayed = new ExitGestureDetectionModeDelayed();
mSendHoverEnterAndMoveDelayed = new SendHoverEnterAndMoveDelayed();
@@ -162,7 +175,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
mDetermineUserIntentTimeout);
if (detector == null) {
- mGestureDetector = new GestureManifold(context, this, mState);
+ mGestureDetector = new GestureManifold(context, this, mState, mHandler);
} else {
mGestureDetector = detector;
}
@@ -196,16 +209,10 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (mState.isTouchExploring()) {
// If a touch exploration gesture is in progress send events for its end.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- } else if (mState.isDragging()) {
- mDraggingPointerId = INVALID_POINTER_ID;
- // Send exit to all pointers that we have delivered.
- mDispatcher.sendUpForInjectedDownPointers(event, policyFlags);
- } else if (mState.isDelegating()) {
- // Send exit to all pointers that we have delivered.
- mDispatcher.sendUpForInjectedDownPointers(event, policyFlags);
- } else if (mState.isGestureDetecting()) {
- // No state specific cleanup required.
}
+ mDraggingPointerId = INVALID_POINTER_ID;
+ // Send exit to any pointers that we have delivered as part of delegating or dragging.
+ mDispatcher.sendUpForInjectedDownPointers(event, policyFlags);
// Remove all pending callbacks.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
@@ -214,6 +221,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendTouchInteractionEndDelayed.cancel();
// Clear the gesture detector
mGestureDetector.clear();
+ // Clear the offset data by long pressing.
+ mDispatcher.clear();
// Go to initial state.
mState.clear();
mAms.onTouchInteractionEnd();
@@ -344,7 +353,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
public boolean onGestureStarted() {
// We have to perform gesture detection, so
// clear the current state and try to detect.
- mState.startGestureDetecting();
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
@@ -533,6 +541,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
}
+
/**
* Handles ACTION_MOVE while in the touch interacting state. This is where transitions to
* delegating and dragging states are handled.
@@ -541,7 +550,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
MotionEvent event, MotionEvent rawEvent, int policyFlags) {
final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
final int pointerIndex = event.findPointerIndex(pointerId);
- final int pointerIdBits = (1 << pointerId);
+ int pointerIdBits = (1 << pointerId);
switch (event.getPointerCount()) {
case 1:
// We have not started sending events since we try to
@@ -552,12 +561,37 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
break;
case 2:
- if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+ if (mGestureDetector.isMultiFingerGesturesEnabled()
+ && !mGestureDetector.isTwoFingerPassthroughEnabled()) {
return;
}
// Make sure we don't have any pending transitions to touch exploration
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
+ if (mGestureDetector.isMultiFingerGesturesEnabled()
+ && mGestureDetector.isTwoFingerPassthroughEnabled()) {
+ if (pointerIndex < 0) {
+ return;
+ }
+ // Require both fingers to have moved a certain amount before starting a drag.
+ for (int index = 0; index < event.getPointerCount(); ++index) {
+ int id = event.getPointerId(index);
+ if (!mReceivedPointerTracker.isReceivedPointerDown(id)) {
+ // Something is wrong with the event stream.
+ Slog.e(LOG_TAG, "Invalid pointer id: " + id);
+ }
+ final float deltaX =
+ mReceivedPointerTracker.getReceivedPointerDownX(id)
+ - rawEvent.getX(index);
+ final float deltaY =
+ mReceivedPointerTracker.getReceivedPointerDownY(id)
+ - rawEvent.getY(index);
+ final double moveDelta = Math.hypot(deltaX, deltaY);
+ if (moveDelta < (2 * mTouchSlop)) {
+ return;
+ }
+ }
+ }
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
// Remove move history before send injected non-move events
@@ -565,12 +599,20 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (isDraggingGesture(event)) {
// Two pointers moving in the same direction within
// a given distance perform a drag.
- mState.startDragging();
- mDraggingPointerId = pointerId;
- adjustEventLocationForDrag(event);
+ computeDraggingPointerIdIfNeeded(event);
+ pointerIdBits = 1 << mDraggingPointerId;
event.setEdgeFlags(mReceivedPointerTracker.getLastReceivedDownEdgeFlags());
- mDispatcher.sendMotionEvent(
- event, MotionEvent.ACTION_DOWN, rawEvent, pointerIdBits, policyFlags);
+ MotionEvent downEvent = computeDownEventForDrag(event);
+ if (downEvent != null) {
+ mDispatcher.sendMotionEvent(downEvent, MotionEvent.ACTION_DOWN, rawEvent,
+ pointerIdBits, policyFlags);
+ mDispatcher.sendMotionEvent(event, MotionEvent.ACTION_MOVE, rawEvent,
+ pointerIdBits, policyFlags);
+ } else {
+ mDispatcher.sendMotionEvent(event, MotionEvent.ACTION_DOWN, rawEvent,
+ pointerIdBits, policyFlags);
+ }
+ mState.startDragging();
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
mState.startDelegating();
@@ -579,12 +621,31 @@ public class TouchExplorer extends BaseEventStreamTransformation
break;
default:
if (mGestureDetector.isMultiFingerGesturesEnabled()) {
- return;
+ if (mGestureDetector.isTwoFingerPassthroughEnabled()) {
+ if (event.getPointerCount() == 3) {
+ // If three fingers went down on the bottom edge of the screen, delegate
+ // immediately.
+ if (allPointersDownOnBottomEdge(event)) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Three-finger edge swipe detected.");
+ }
+ mState.startDelegating();
+ if (mState.isTouchExploring()) {
+ mDispatcher.sendDownForAllNotInjectedPointers(event,
+ policyFlags);
+ } else {
+ mDispatcher.sendDownForAllNotInjectedPointersWithOriginalDown(
+ event, policyFlags);
+ }
+ }
+ }
+ }
+ } else {
+ // More than two pointers are delegated to the view hierarchy.
+ mState.startDelegating();
+ event = MotionEvent.obtainNoHistory(event);
+ mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
}
- // More than two pointers are delegated to the view hierarchy.
- mState.startDelegating();
- event = MotionEvent.obtainNoHistory(event);
- mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
break;
}
}
@@ -626,7 +687,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
event, MotionEvent.ACTION_HOVER_MOVE, rawEvent, pointerIdBits, policyFlags);
break;
case 2:
- if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+ if (mGestureDetector.isMultiFingerGesturesEnabled()
+ && !mGestureDetector.isTwoFingerPassthroughEnabled()) {
return;
}
if (mSendHoverEnterAndMoveDelayed.isPending()) {
@@ -681,7 +743,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
*/
private void handleMotionEventStateDragging(
MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (mGestureDetector.isMultiFingerGesturesEnabled()) {
+ if (mGestureDetector.isMultiFingerGesturesEnabled()
+ && !mGestureDetector.isTwoFingerPassthroughEnabled()) {
// Multi-finger gestures conflict with this functionality.
return;
}
@@ -723,7 +786,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
case 2: {
if (isDraggingGesture(event)) {
// If still dragging send a drag event.
- adjustEventLocationForDrag(event);
+ computeDraggingPointerIdIfNeeded(event);
mDispatcher.sendMotionEvent(
event,
MotionEvent.ACTION_MOVE,
@@ -734,6 +797,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
// The two pointers are moving either in different directions or
// no close enough => delegate the gesture to the view hierarchy.
mState.startDelegating();
+ mDraggingPointerId = INVALID_POINTER_ID;
// Remove move history before send injected non-move events
event = MotionEvent.obtainNoHistory(event);
// Send an event to the end of the drag gesture.
@@ -749,6 +813,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
} break;
default: {
mState.startDelegating();
+ mDraggingPointerId = INVALID_POINTER_ID;
event = MotionEvent.obtainNoHistory(event);
// Send an event to the end of the drag gesture.
mDispatcher.sendMotionEvent(
@@ -772,17 +837,15 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
} break;
case MotionEvent.ACTION_UP: {
- mAms.onTouchInteractionEnd();
- // Announce the end of a new touch interaction.
- mDispatcher.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
final int pointerId = event.getPointerId(event.getActionIndex());
if (pointerId == mDraggingPointerId) {
- mDraggingPointerId = INVALID_POINTER_ID;
- // Send an event to the end of the drag gesture.
mDispatcher.sendMotionEvent(
event, MotionEvent.ACTION_UP, rawEvent, pointerIdBits, policyFlags);
}
+ mAms.onTouchInteractionEnd();
+ // Announce the end of a new touch interaction.
+ mDispatcher.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
} break;
}
}
@@ -901,21 +964,104 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
/**
- * Adjust the location of an injected event when performing a drag The new location will be in
- * between the two fingers touching the screen.
+ * Computes {@link #mDraggingPointerId} if it is invalid. The pointer will be the finger
+ * closet to an edge of the screen.
*/
- private void adjustEventLocationForDrag(MotionEvent event) {
-
+ private void computeDraggingPointerIdIfNeeded(MotionEvent event) {
+ if (mDraggingPointerId != INVALID_POINTER_ID) {
+ // If we have a valid pointer ID, we should be good
+ final int pointerIndex = event.findPointerIndex(mDraggingPointerId);
+ if (event.findPointerIndex(pointerIndex) >= 0) {
+ return;
+ }
+ }
+ // Use the pointer that is closest to its closest edge.
final float firstPtrX = event.getX(0);
final float firstPtrY = event.getY(0);
+ final int firstPtrId = event.getPointerId(0);
final float secondPtrX = event.getX(1);
final float secondPtrY = event.getY(1);
- final int pointerIndex = event.findPointerIndex(mDraggingPointerId);
- final float deltaX =
- (pointerIndex == 0) ? (secondPtrX - firstPtrX) : (firstPtrX - secondPtrX);
- final float deltaY =
- (pointerIndex == 0) ? (secondPtrY - firstPtrY) : (firstPtrY - secondPtrY);
- event.offsetLocation(deltaX / 2, deltaY / 2);
+ final int secondPtrId = event.getPointerId(1);
+ mDraggingPointerId = (getDistanceToClosestEdge(firstPtrX, firstPtrY)
+ < getDistanceToClosestEdge(secondPtrX, secondPtrY))
+ ? firstPtrId : secondPtrId;
+ }
+
+ private float getDistanceToClosestEdge(float x, float y) {
+ final long width = mContext.getResources().getDisplayMetrics().widthPixels;
+ final long height = mContext.getResources().getDisplayMetrics().heightPixels;
+ float distance = Float.MAX_VALUE;
+ if (x < (width - x)) {
+ distance = x;
+ } else {
+ distance = width - x;
+ }
+ if (distance > y) {
+ distance = y;
+ }
+ if (distance > (height - y)) {
+ distance = (height - y);
+ }
+ return distance;
+ }
+
+ /**
+ * Creates a down event using the down coordinates of the dragging pointer and other information
+ * from the supplied event. The supplied event's down time is adjusted to reflect the time when
+ * the dragging pointer initially went down.
+ */
+ private MotionEvent computeDownEventForDrag(MotionEvent event) {
+ // Creating a down event only makes sense if we haven't started touch exploring yet.
+ if (mState.isTouchExploring()
+ || mDraggingPointerId == INVALID_POINTER_ID
+ || event == null) {
+ return null;
+ }
+ final float x = mReceivedPointerTracker.getReceivedPointerDownX(mDraggingPointerId);
+ final float y = mReceivedPointerTracker.getReceivedPointerDownY(mDraggingPointerId);
+ final long time = mReceivedPointerTracker.getReceivedPointerDownTime(mDraggingPointerId);
+ MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[1];
+ coords[0] = new MotionEvent.PointerCoords();
+ coords[0].x = x;
+ coords[0].y = y;
+ MotionEvent.PointerProperties[] properties = new MotionEvent.PointerProperties[1];
+ properties[0] = new MotionEvent.PointerProperties();
+ properties[0].id = mDraggingPointerId;
+ properties[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
+ MotionEvent downEvent =
+ MotionEvent.obtain(
+ time,
+ time,
+ MotionEvent.ACTION_DOWN,
+ 1,
+ properties,
+ coords,
+ event.getMetaState(),
+ event.getButtonState(),
+ event.getXPrecision(),
+ event.getYPrecision(),
+ event.getDeviceId(),
+ event.getEdgeFlags(),
+ event.getSource(),
+ event.getFlags());
+ event.setDownTime(time);
+ return downEvent;
+ }
+
+ private boolean allPointersDownOnBottomEdge(MotionEvent event) {
+ final long screenHeight =
+ mContext.getResources().getDisplayMetrics().heightPixels;
+ for (int i = 0; i < event.getPointerCount(); ++i) {
+ final int pointerId = event.getPointerId(i);
+ final float pointerDownY = mReceivedPointerTracker.getReceivedPointerDownY(pointerId);
+ if (pointerDownY < (screenHeight - mEdgeSwipeHeightPixels)) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "The pointer is not on the bottom edge" + pointerDownY);
+ }
+ return false;
+ }
+ }
+ return true;
}
public TouchState getState() {
@@ -944,6 +1090,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
mGestureDetector.setMultiFingerGesturesEnabled(enabled);
}
+ /**
+ * This function turns on and off two-finger passthrough gestures such as drag and pinch when
+ * multi-finger gestures are enabled.
+ */
+ public void setTwoFingerPassthroughEnabled(boolean enabled) {
+ mGestureDetector.setTwoFingerPassthroughEnabled(enabled);
+ }
public void setGestureDetectionPassthroughRegion(Region region) {
mGestureDetectionPassthroughRegion = region;
}
@@ -953,7 +1106,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
private boolean shouldPerformGestureDetection(MotionEvent event) {
- if (mState.isDelegating()) {
+ if (mState.isDelegating() || mState.isDragging()) {
return false;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -1046,6 +1199,15 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
public void run() {
+ if (mReceivedPointerTracker.getReceivedPointerDownCount() > 1) {
+ // Multi-finger touch exploration doesn't make sense.
+ Slog.e(
+ LOG_TAG,
+ "Attempted touch exploration with "
+ + mReceivedPointerTracker.getReceivedPointerDownCount()
+ + " pointers down.");
+ return;
+ }
// Send an accessibility event to announce the touch exploration start.
mDispatcher.sendAccessibilityEvent(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index 7a39bc29e8e5..6dabe76c7dc9 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -208,7 +208,9 @@ public class TouchState {
startGestureDetecting();
break;
case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
- startTouchInteracting();
+ // Clear to make sure that we don't accidentally execute passthrough, and that we
+ // are ready for the next interaction.
+ clear();
break;
default:
break;
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a704c58a9b70..ad91924c1e63 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -300,6 +300,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
mFindDeviceCallback = callback;
mRequest = request;
mCallingPackage = callingPackage;
+ request.setCallingPackage(callingPackage);
callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
final long callingIdentity = Binder.clearCallingIdentity();
@@ -308,7 +309,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
AndroidFuture<Association> future = new AndroidFuture<>();
service.startDiscovery(request, callingPackage, callback, future);
return future;
- }).whenComplete(uncheckExceptions((association, err) -> {
+ }).cancelTimeout().whenComplete(uncheckExceptions((association, err) -> {
if (err == null) {
addAssociation(association);
} else {
@@ -372,7 +373,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
checkArgument(getCallingUserId() == userId,
"Must be called by either same user or system");
- mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
+ int callingUid = Binder.getCallingUid();
+ if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
+ }
}
@Override
@@ -561,7 +565,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
if (DEBUG) {
Log.i(LOG_TAG, "recordAssociation(" + association + ")");
}
- updateAssociations(associations -> CollectionUtils.add(associations, association));
+ updateAssociations(associations -> CollectionUtils.add(associations, association),
+ association.userId);
}
private void recordAssociation(String privilegedPackage, String deviceAddress) {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 4b9d0f1266f5..f6326eb0d78a 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,4 +1,11 @@
filegroup {
+ name: "services.core-sources-deviceconfig-interface",
+ srcs: [
+ "java/com/android/server/utils/DeviceConfigInterface.java"
+ ],
+}
+
+filegroup {
name: "services.core-sources",
srcs: ["java/**/*.java"],
exclude_srcs: [":connectivity-service-srcs"],
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 1cdc95a46f81..eb1123e47f52 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -315,11 +315,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
mPreciseDataConnectionStates;
- static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
- PhoneStateListener.LISTEN_REGISTRATION_FAILURE
- | PhoneStateListener.LISTEN_BARRING_INFO;
-
- static final int ENFORCE_FINE_LOCATION_PERMISSION_MASK =
+ // Starting in Q, almost all cellular location requires FINE location enforcement.
+ // Prior to Q, cellular was available with COARSE location enforcement. Bits in this
+ // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later.
+ static final int ENFORCE_LOCATION_PERMISSION_MASK =
PhoneStateListener.LISTEN_CELL_LOCATION
| PhoneStateListener.LISTEN_CELL_INFO
| PhoneStateListener.LISTEN_REGISTRATION_FAILURE
@@ -376,7 +375,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " newDefaultPhoneId=" + newDefaultPhoneId);
}
- //Due to possible risk condition,(notify call back using the new
+ //Due to possible race condition,(notify call back using the new
//defaultSubId comes before new defaultSubId update) we need to recall all
//possible missed notify callback
synchronized (mRecords) {
@@ -909,7 +908,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
// null will be translated to empty CellLocation object in client.
r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
@@ -964,7 +964,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
+ mCellInfo.get(phoneId));
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
}
} catch (RemoteException ex) {
@@ -1518,7 +1519,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
idMatch(r.subId, subId, phoneId) &&
- checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
try {
if (DBG_LOC) {
log("notifyCellInfoForSubscriber: mCellInfo=" + cellInfo
@@ -1797,7 +1799,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
- checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
try {
if (DBG_LOC) {
log("notifyCellLocation: cellIdentity=" + cellIdentity
@@ -2542,19 +2545,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
.setCallingPid(Binder.getCallingPid())
.setCallingUid(Binder.getCallingUid());
- boolean shouldCheckLocationPermissions = false;
- if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
- locationQueryBuilder.setMinSdkVersionForCoarse(0);
- shouldCheckLocationPermissions = true;
- }
-
- if ((events & ENFORCE_FINE_LOCATION_PERMISSION_MASK) != 0) {
+ if ((events & ENFORCE_LOCATION_PERMISSION_MASK) != 0) {
// Everything that requires fine location started in Q. So far...
locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q);
- shouldCheckLocationPermissions = true;
- }
+ // If we're enforcing fine starting in Q, we also want to enforce coarse even for
+ // older SDK versions.
+ locationQueryBuilder.setMinSdkVersionForCoarse(0);
- if (shouldCheckLocationPermissions) {
LocationAccessPolicy.LocationPermissionResult result =
LocationAccessPolicy.checkLocationPermission(
mContext, locationQueryBuilder.build());
@@ -2721,8 +2718,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
mServiceState[phoneId]);
- r.callback.onServiceStateChanged(
- new ServiceState(mServiceState[phoneId]));
+ ServiceState ss = new ServiceState(mServiceState[phoneId]);
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(ss);
+ } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(
+ ss.createLocationInfoSanitizedCopy(false));
+ } else {
+ r.callback.onServiceStateChanged(
+ ss.createLocationInfoSanitizedCopy(true));
+ }
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2767,7 +2772,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
+ mCellInfo.get(phoneId));
}
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
}
} catch (RemoteException ex) {
@@ -2833,7 +2839,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
+ mCellIdentity[phoneId]);
}
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
// null will be translated to empty CellLocation object in client.
r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index daae1a11059c..4ff6dac08b85 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -327,6 +327,13 @@ final class UiModeManagerService extends SystemService {
mCurrentUser = userHandle;
getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver);
verifySetupWizardCompleted();
+ synchronized (mLock) {
+ // only update if the value is actually changed
+ if (updateNightModeFromSettingsLocked(getContext(), getContext().getResources(),
+ mCurrentUser)) {
+ updateLocked(0, 0);
+ }
+ }
}
@Override
@@ -354,11 +361,10 @@ final class UiModeManagerService extends SystemService {
new IntentFilter(Intent.ACTION_DOCK_EVENT));
IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
context.registerReceiver(mBatteryReceiver, batteryFilter);
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
context.registerReceiver(mSettingsRestored,
new IntentFilter(Intent.ACTION_SETTING_RESTORED));
- context.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
+ context.registerReceiver(mOnShutdown,
+ new IntentFilter(Intent.ACTION_SHUTDOWN));
updateConfigurationLocked();
applyConfigurationExternallyLocked();
}
@@ -405,6 +411,21 @@ final class UiModeManagerService extends SystemService {
publishLocalService(UiModeManagerInternal.class, mLocalService);
}
+ private final BroadcastReceiver mOnShutdown = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mNightMode == MODE_NIGHT_AUTO) {
+ persistComputedNightMode(mCurrentUser);
+ }
+ }
+ };
+
+ private void persistComputedNightMode(int userId) {
+ Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE_LAST_COMPUTED, mComputedNightMode ? 1 : 0,
+ userId);
+ }
+
private final BroadcastReceiver mSettingsRestored = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -506,6 +527,10 @@ final class UiModeManagerService extends SystemService {
Secure.getLongForUser(context.getContentResolver(),
Secure.DARK_THEME_CUSTOM_END_TIME,
DEFAULT_CUSTOM_NIGHT_END_TIME.toNanoOfDay() / 1000L, userId) * 1000);
+ if (mNightMode == MODE_NIGHT_AUTO) {
+ mComputedNightMode = Secure.getIntForUser(context.getContentResolver(),
+ Secure.UI_NIGHT_MODE_LAST_COMPUTED, 0, userId) != 0;
+ }
}
return oldNightMode != mNightMode;
@@ -1596,18 +1621,4 @@ final class UiModeManagerService extends SystemService {
}
}
}
-
- private final class UserSwitchedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (mLock) {
- final int currentId = intent.getIntExtra(
- Intent.EXTRA_USER_HANDLE, USER_SYSTEM);
- // only update if the value is actually changed
- if (updateNightModeFromSettingsLocked(context, context.getResources(), currentId)) {
- updateLocked(0, 0);
- }
- }
- }
- }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e4cdfe92ec8a..f134df762b52 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7142,67 +7142,68 @@ public class ActivityManagerService extends IActivityManager.Stub
"getContentProviderImpl: after checkContentProviderPermission");
final long origId = Binder.clearCallingIdentity();
+ try {
+ checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
+
+ // Return the provider instance right away since it already exists.
+ conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage,
+ callingTag, stable);
+ if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
+ if (cpr.proc != null
+ && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ // If this is a perceptible app accessing the provider,
+ // make sure to count it as being accessed and thus
+ // back up on the LRU list. This is good because
+ // content providers are often expensive to start.
+ checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
+ mProcessList.updateLruProcessLocked(cpr.proc, false, null);
+ checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
+ }
+ }
- checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
-
- // In this case the provider instance already exists, so we can
- // return it right away.
- conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
- stable);
- if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
- if (cpr.proc != null
- && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
- // If this is a perceptible app accessing the provider,
- // make sure to count it as being accessed and thus
- // back up on the LRU list. This is good because
- // content providers are often expensive to start.
- checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
- mProcessList.updateLruProcessLocked(cpr.proc, false, null);
- checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
- }
- }
-
- checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
- final int verifiedAdj = cpr.proc.verifiedAdj;
- boolean success = updateOomAdjLocked(cpr.proc, true,
- OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
- // XXX things have changed so updateOomAdjLocked doesn't actually tell us
- // if the process has been successfully adjusted. So to reduce races with
- // it, we will check whether the process still exists. Note that this doesn't
- // completely get rid of races with LMK killing the process, but should make
- // them much smaller.
- if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
- success = false;
- }
- maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
- checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
- if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
- // NOTE: there is still a race here where a signal could be
- // pending on the process even though we managed to update its
- // adj level. Not sure what to do about this, but at least
- // the race is now smaller.
- if (!success) {
- // Uh oh... it looks like the provider's process
- // has been killed on us. We need to wait for a new
- // process to be started, and make sure its death
- // doesn't kill our process.
- Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString()
- + " is crashing; detaching " + r);
- boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- if (!lastRef) {
- // This wasn't the last ref our process had on
- // the provider... we will be killed during cleaning up, bail.
- return null;
+ checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
+ final int verifiedAdj = cpr.proc.verifiedAdj;
+ boolean success = updateOomAdjLocked(cpr.proc, true,
+ OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
+ // XXX things have changed so updateOomAdjLocked doesn't actually tell us
+ // if the process has been successfully adjusted. So to reduce races with
+ // it, we will check whether the process still exists. Note that this doesn't
+ // completely get rid of races with LMK killing the process, but should make
+ // them much smaller.
+ if (success && verifiedAdj != cpr.proc.setAdj
+ && !isProcessAliveLocked(cpr.proc)) {
+ success = false;
+ }
+ maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
+ checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
+ if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
+ // NOTE: there is still a race here where a signal could be
+ // pending on the process even though we managed to update its
+ // adj level. Not sure what to do about this, but at least
+ // the race is now smaller.
+ if (!success) {
+ // Uh oh... it looks like the provider's process
+ // has been killed on us. We need to wait for a new
+ // process to be started, and make sure its death
+ // doesn't kill our process.
+ Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ + " is crashing; detaching " + r);
+ boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
+ if (!lastRef) {
+ // This wasn't the last ref our process had on
+ // the provider... we will be killed during cleaning up, bail.
+ return null;
+ }
+ // We'll just start a new process to host the content provider
+ providerRunning = false;
+ conn = null;
+ dyingProc = cpr.proc;
+ } else {
+ cpr.proc.verifiedAdj = cpr.proc.setAdj;
}
- // We'll just start a new process to host the content provider
- providerRunning = false;
- conn = null;
- dyingProc = cpr.proc;
- } else {
- cpr.proc.verifiedAdj = cpr.proc.setAdj;
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
-
- Binder.restoreCallingIdentity(origId);
}
if (!providerRunning) {
@@ -10459,12 +10460,10 @@ public class ActivityManagerService extends IActivityManager.Stub
} finally {
Binder.restoreCallingIdentity(identity);
}
- if (uid == Process.INVALID_UID) {
- return Process.INVALID_UID;
- }
+ // If the uid is Process.INVALID_UID, the below 'if' check will be always true
if (UserHandle.getAppId(uid) != UserHandle.getAppId(callingUid)) {
// Requires the DUMP permission if the target package doesn't belong
- // to the caller.
+ // to the caller or it doesn't exist.
enforceCallingPermission(android.Manifest.permission.DUMP, function);
}
return uid;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a2eea1348d5c..9a6f130cfd5d 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -791,7 +791,10 @@ public final class BroadcastQueue {
mService.updateOomAdjLocked(r.curApp, true,
OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
}
+ } else if (filter.receiverList.app != null) {
+ mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(filter.receiverList.app);
}
+
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
@@ -1121,6 +1124,10 @@ public final class BroadcastQueue {
}
}
if (sendResult) {
+ if (r.callerApp != null) {
+ mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(
+ r.callerApp);
+ }
try {
if (DEBUG_BROADCAST) {
Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] "
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 8112bb854b71..36d4a38c1624 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -720,6 +720,16 @@ public final class CachedAppOptimizer {
}
}
+ // This will ensure app will be out of the freezer for at least FREEZE_TIMEOUT_MS
+ void unfreezeTemporarily(ProcessRecord app) {
+ synchronized (mAm) {
+ if (app.frozen) {
+ unfreezeAppLocked(app);
+ freezeAppAsync(app);
+ }
+ }
+ }
+
@GuardedBy("mAm")
void freezeAppAsync(ProcessRecord app) {
mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
@@ -777,27 +787,27 @@ public final class CachedAppOptimizer {
long freezeTime = app.freezeUnfreezeTime;
try {
+ freezeBinder(app.pid, false);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
+ + ". Killing it");
+ app.kill("Unable to unfreeze",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ return;
+ }
+
+ try {
Process.setProcessFrozen(app.pid, app.uid, false);
app.freezeUnfreezeTime = SystemClock.uptimeMillis();
app.frozen = false;
} catch (Exception e) {
Slog.e(TAG_AM, "Unable to unfreeze " + app.pid + " " + app.processName
- + ". Any related user experience might be hanged.");
+ + ". This might cause inconsistency or UI hangs.");
}
if (!app.frozen) {
- try {
- freezeBinder(app.pid, false);
- } catch (RuntimeException e) {
- Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
- + ". Killing it");
- app.kill("Unable to unfreeze",
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
- return;
- }
-
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName);
}
@@ -1110,14 +1120,6 @@ public final class CachedAppOptimizer {
return;
}
- try {
- freezeBinder(pid, true);
- } catch (RuntimeException e) {
- // TODO: it might be preferable to kill the target pid in this case
- Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
- return;
- }
-
if (pid == 0 || proc.frozen) {
// Already frozen or not a real process, either one being
// launched or one being killed
@@ -1146,6 +1148,15 @@ public final class CachedAppOptimizer {
EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
+ try {
+ freezeBinder(pid, true);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
+ proc.kill("Unable to freeze binder interface",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ }
+
// See above for why we're not taking mPhenotypeFlagLock here
if (mRandom.nextFloat() < mFreezerStatsdSampleRate) {
FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 640d99f71ebe..46255f5dac27 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1011,10 +1011,11 @@ public class AppOpsService extends IAppOpsService.Stub {
}
int numInProgressEvents = mInProgressEvents.size();
+ List<IBinder> binders = new ArrayList<>(mInProgressEvents.keySet());
for (int i = 0; i < numInProgressEvents; i++) {
- InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
+ InProgressStartOpEvent event = mInProgressEvents.get(binders.get(i));
- if (event.getUidState() != newState) {
+ if (event != null && event.getUidState() != newState) {
try {
// Remove all but one unfinished start count and then call finished() to
// remove start event object
@@ -1025,7 +1026,10 @@ public class AppOpsService extends IAppOpsService.Stub {
// Call started() to add a new start event object and then add the
// previously removed unfinished start counts back
started(event.getClientId(), newState, false);
- event.numUnfinishedStarts += numPreviousUnfinishedStarts - 1;
+ InProgressStartOpEvent newEvent = mInProgressEvents.get(binders.get(i));
+ if (newEvent != null) {
+ newEvent.numUnfinishedStarts += numPreviousUnfinishedStarts - 1;
+ }
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "Cannot switch to new uidState " + newState);
}
@@ -2989,9 +2993,14 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_IGNORED;
}
+ // This is a workaround for R QPR, new API change is not allowed. We only allow the current
+ // voice recognizer is also the voice interactor to noteproxy op.
+ final boolean isTrustVoiceServiceProxy =
+ AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy || isSelfBlame;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 3d22a156b91c..f49b5dca2b08 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -669,10 +669,12 @@ final class HistoricalRegistry {
void shutdown() {
synchronized (mInMemoryLock) {
- if (mMode != AppOpsManager.HISTORICAL_MODE_DISABLED) {
- persistPendingHistory();
+ if (mMode == AppOpsManager.HISTORICAL_MODE_DISABLED) {
+ return;
}
}
+ // Do not call persistPendingHistory inside the memory lock, due to possible deadlock
+ persistPendingHistory();
}
void persistPendingHistory() {
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index ef1b574c29a8..b4d74e0900f9 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -16,16 +16,22 @@
package com.android.server.biometrics;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.security.KeyStore;
+import android.util.EventLog;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.List;
/**
* A class to keep track of the authentication state for a given client.
@@ -148,7 +154,54 @@ public abstract class AuthenticationClient extends ClientMonitor {
+ ", requireConfirmation: " + mRequireConfirmation
+ ", user: " + getTargetUserId());
+ // Ensure authentication only succeeds if the client activity is on top or is keyguard.
+ boolean isBackgroundAuth = false;
+ if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())) {
+ try {
+ final List<ActivityManager.RunningTaskInfo> tasks =
+ ActivityTaskManager.getService().getTasks(1);
+ if (tasks == null || tasks.isEmpty()) {
+ Slog.e(TAG, "No running tasks reported");
+ isBackgroundAuth = true;
+ } else {
+ final ComponentName topActivity = tasks.get(0).topActivity;
+ if (topActivity == null) {
+ Slog.e(TAG, "Unable to get top activity");
+ isBackgroundAuth = true;
+ } else {
+ final String topPackage = topActivity.getPackageName();
+ if (!topPackage.contentEquals(getOwnerString())) {
+ Slog.e(TAG, "Background authentication detected, top: " + topPackage
+ + ", client: " + this);
+ isBackgroundAuth = true;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get running tasks", e);
+ isBackgroundAuth = true;
+ }
+ }
+
+ // Fail authentication if we can't confirm the client activity is on top.
+ if (isBackgroundAuth) {
+ Slog.e(TAG, "Failing possible background authentication");
+ authenticated = false;
+
+ // SafetyNet logging for exploitation attempts of b/159249069.
+ final ApplicationInfo appInfo = getContext().getApplicationInfo();
+ EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
+ "Attempted background authentication");
+ }
+
if (authenticated) {
+ // SafetyNet logging for b/159249069 if constraint is violated.
+ if (isBackgroundAuth) {
+ final ApplicationInfo appInfo = getContext().getApplicationInfo();
+ EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
+ "Successful background authentication!");
+ }
+
mAlreadyDone = true;
if (listener != null) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index a0eafb4fc93f..b7e188c73eab 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -392,6 +392,7 @@ class RadioModule {
} catch (RemoteException ex) {
Slog.e(TAG, "Failed closing announcement listener", ex);
}
+ hwCloseHandle.value = null;
}
};
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 24661d69a78e..852868616afd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -86,6 +86,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
@@ -2191,10 +2192,16 @@ public final class DisplayManagerService extends SystemService {
}
}
- if (callingUid == Process.SYSTEM_UID
- || checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
- flags |= VIRTUAL_DISPLAY_FLAG_TRUSTED;
- } else {
+ if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
+ if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+ EventLog.writeEvent(0x534e4554, "162627132", callingUid,
+ "Attempt to create a trusted display without holding permission!");
+ throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ + "create a trusted virtual display.");
+ }
+ }
+
+ if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index baa43cfd92f1..e30b1ebdbe2a 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -46,8 +46,10 @@ import android.view.DisplayInfo;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
+import com.android.server.utils.DeviceConfigInterface;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -64,9 +66,11 @@ public class DisplayModeDirector {
private static final boolean DEBUG = false;
private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1;
- private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
+ private static final int MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
- private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
+ private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4;
+ private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
+ private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
// Special ID used to indicate that given vote is to be applied globally, rather than to a
// specific display.
@@ -79,6 +83,13 @@ public class DisplayModeDirector {
private final Context mContext;
private final DisplayModeDirectorHandler mHandler;
+ private final Injector mInjector;
+
+ private final AppRequestObserver mAppRequestObserver;
+ private final SettingsObserver mSettingsObserver;
+ private final DisplayObserver mDisplayObserver;
+ private final DeviceConfigInterface mDeviceConfig;
+ private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
// A map from the display ID to the collection of votes and their priority. The latter takes
// the form of another map from the priority to the vote itself so that each priority is
@@ -89,17 +100,19 @@ public class DisplayModeDirector {
// A map from the display ID to the default mode of that display.
private SparseArray<Display.Mode> mDefaultModeByDisplay;
- private final AppRequestObserver mAppRequestObserver;
- private final SettingsObserver mSettingsObserver;
- private final DisplayObserver mDisplayObserver;
private BrightnessObserver mBrightnessObserver;
- private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
+ this(context, handler, new RealInjector());
+ }
+
+ public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
+ @NonNull Injector injector) {
mContext = context;
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
+ mInjector = injector;
mVotesByDisplay = new SparseArray<>();
mSupportedModesByDisplay = new SparseArray<>();
mDefaultModeByDisplay = new SparseArray<>();
@@ -108,6 +121,7 @@ public class DisplayModeDirector {
mDisplayObserver = new DisplayObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler);
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
+ mDeviceConfig = injector.getDeviceConfig();
}
/**
@@ -348,6 +362,23 @@ public class DisplayModeDirector {
}
/**
+ * Retrieve the Vote for the given display and priority. Intended only for testing purposes.
+ *
+ * @param displayId the display to query for
+ * @param priority the priority of the vote to return
+ * @return the vote corresponding to the given {@code displayId} and {@code priority},
+ * or {@code null} if there isn't one
+ */
+ @VisibleForTesting
+ @Nullable
+ Vote getVote(int displayId, int priority) {
+ synchronized (mLock) {
+ SparseArray<Vote> votes = getVotesLocked(displayId);
+ return votes.get(priority);
+ }
+ }
+
+ /**
* Print the object's state and debug information into the given stream.
*
* @param pw The stream to dump information to.
@@ -465,6 +496,17 @@ public class DisplayModeDirector {
}
@VisibleForTesting
+ BrightnessObserver getBrightnessObserver() {
+ return mBrightnessObserver;
+ }
+
+ @VisibleForTesting
+ SettingsObserver getSettingsObserver() {
+ return mSettingsObserver;
+ }
+
+
+ @VisibleForTesting
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
synchronized (mLock) {
@@ -492,16 +534,35 @@ public class DisplayModeDirector {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
+ case MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED: {
+ Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
+ mBrightnessObserver.onDeviceConfigLowBrightnessThresholdsChanged(
+ thresholds.first, thresholds.second);
+ break;
+ }
+
+ case MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED: {
+ int refreshRateInZone = msg.arg1;
+ mBrightnessObserver.onDeviceConfigRefreshRateInLowZoneChanged(
+ refreshRateInZone);
+ break;
+ }
+
+ case MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED: {
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
- if (thresholds != null) {
- mBrightnessObserver.onDeviceConfigThresholdsChanged(
- thresholds.first, thresholds.second);
- } else {
- mBrightnessObserver.onDeviceConfigThresholdsChanged(null, null);
- }
+ mBrightnessObserver.onDeviceConfigHighBrightnessThresholdsChanged(
+ thresholds.first, thresholds.second);
+
+ break;
+ }
+
+ case MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED: {
+ int refreshRateInZone = msg.arg1;
+ mBrightnessObserver.onDeviceConfigRefreshRateInHighZoneChanged(
+ refreshRateInZone);
break;
+ }
case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
Float defaultPeakRefreshRate = (Float) msg.obj;
@@ -509,12 +570,6 @@ public class DisplayModeDirector {
defaultPeakRefreshRate);
break;
- case MSG_REFRESH_RATE_IN_ZONE_CHANGED:
- int refreshRateInZone = msg.arg1;
- mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
- refreshRateInZone);
- break;
-
case MSG_REFRESH_RATE_RANGE_CHANGED:
DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
(DesiredDisplayModeSpecsListener) msg.obj;
@@ -684,10 +739,11 @@ public class DisplayModeDirector {
// by all other considerations. It acts to set a default frame rate for a device.
public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
- // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
+ // FLICKER votes for a single refresh rate like [60,60], [90,90] or null.
// If the higher voters result is a range, it will fix the rate to a single choice.
- // It's used to avoid rate switch in certain conditions.
- public static final int PRIORITY_LOW_BRIGHTNESS = 1;
+ // It's used to avoid refresh rate switches in certain conditions which may result in the
+ // user seeing the display flickering when the switches occur.
+ public static final int PRIORITY_FLICKER = 1;
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
@@ -760,8 +816,8 @@ public class DisplayModeDirector {
switch (priority) {
case PRIORITY_DEFAULT_REFRESH_RATE:
return "PRIORITY_DEFAULT_REFRESH_RATE";
- case PRIORITY_LOW_BRIGHTNESS:
- return "PRIORITY_LOW_BRIGHTNESS";
+ case PRIORITY_FLICKER:
+ return "PRIORITY_FLICKER";
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
case PRIORITY_APP_REQUEST_REFRESH_RATE:
@@ -786,7 +842,8 @@ public class DisplayModeDirector {
}
}
- private final class SettingsObserver extends ContentObserver {
+ @VisibleForTesting
+ final class SettingsObserver extends ContentObserver {
private final Uri mPeakRefreshRateSetting =
Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
private final Uri mMinRefreshRateSetting =
@@ -809,8 +866,7 @@ public class DisplayModeDirector {
public void observe() {
final ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(mPeakRefreshRateSetting, false /*notifyDescendants*/, this,
- UserHandle.USER_SYSTEM);
+ mInjector.registerPeakRefreshRateObserver(cr, this);
cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this,
UserHandle.USER_SYSTEM);
cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
@@ -828,6 +884,13 @@ public class DisplayModeDirector {
}
}
+ public void setDefaultRefreshRate(float refreshRate) {
+ synchronized (mLock) {
+ mDefaultRefreshRate = refreshRate;
+ updateRefreshRateSettingLocked();
+ }
+ }
+
public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) {
if (defaultPeakRefreshRate == null) {
defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
@@ -1032,6 +1095,7 @@ public class DisplayModeDirector {
@Override
public void onDisplayChanged(int displayId) {
updateDisplayModes(displayId);
+ // TODO: Break the coupling between DisplayObserver and BrightnessObserver.
mBrightnessObserver.onDisplayChanged(displayId);
}
@@ -1070,15 +1134,16 @@ public class DisplayModeDirector {
*/
@VisibleForTesting
public class BrightnessObserver extends ContentObserver {
- // TODO: brightnessfloat: change this to the float setting
- private final Uri mDisplayBrightnessSetting =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
private final static int LIGHT_SENSOR_RATE_MS = 250;
- private int[] mDisplayBrightnessThresholds;
- private int[] mAmbientBrightnessThresholds;
+ private int[] mLowDisplayBrightnessThresholds;
+ private int[] mLowAmbientBrightnessThresholds;
+ private int[] mHighDisplayBrightnessThresholds;
+ private int[] mHighAmbientBrightnessThresholds;
// valid threshold if any item from the array >= 0
- private boolean mShouldObserveDisplayChange;
- private boolean mShouldObserveAmbientChange;
+ private boolean mShouldObserveDisplayLowChange;
+ private boolean mShouldObserveAmbientLowChange;
+ private boolean mShouldObserveDisplayHighChange;
+ private boolean mShouldObserveAmbientHighChange;
private SensorManager mSensorManager;
private Sensor mLightSensor;
@@ -1086,46 +1151,122 @@ public class DisplayModeDirector {
// Take it as low brightness before valid sensor data comes
private float mAmbientLux = -1.0f;
private AmbientFilter mAmbientFilter;
+ private int mBrightness = -1;
private final Context mContext;
- // Enable light sensor only when mShouldObserveAmbientChange is true, screen is on, peak
- // refresh rate changeable and low power mode off. After initialization, these states will
+ // Enable light sensor only when mShouldObserveAmbientLowChange is true or
+ // mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate
+ // changeable and low power mode off. After initialization, these states will
// be updated from the same handler thread.
- private boolean mScreenOn = false;
+ private boolean mDefaultDisplayOn = false;
private boolean mRefreshRateChangeable = false;
private boolean mLowPowerModeEnabled = false;
- private int mRefreshRateInZone;
+ private int mRefreshRateInLowZone;
+ private int mRefreshRateInHighZone;
BrightnessObserver(Context context, Handler handler) {
super(handler);
mContext = context;
- mDisplayBrightnessThresholds = context.getResources().getIntArray(
+ mLowDisplayBrightnessThresholds = context.getResources().getIntArray(
R.array.config_brightnessThresholdsOfPeakRefreshRate);
- mAmbientBrightnessThresholds = context.getResources().getIntArray(
+ mLowAmbientBrightnessThresholds = context.getResources().getIntArray(
R.array.config_ambientThresholdsOfPeakRefreshRate);
- if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) {
- throw new RuntimeException("display brightness threshold array and ambient "
- + "brightness threshold array have different length");
+ if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) {
+ throw new RuntimeException("display low brightness threshold array and ambient "
+ + "brightness threshold array have different length: "
+ + "displayBrightnessThresholds="
+ + Arrays.toString(mLowDisplayBrightnessThresholds)
+ + ", ambientBrightnessThresholds="
+ + Arrays.toString(mLowAmbientBrightnessThresholds));
}
+
+ mHighDisplayBrightnessThresholds = context.getResources().getIntArray(
+ R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
+ mHighAmbientBrightnessThresholds = context.getResources().getIntArray(
+ R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
+ if (mHighDisplayBrightnessThresholds.length
+ != mHighAmbientBrightnessThresholds.length) {
+ throw new RuntimeException("display high brightness threshold array and ambient "
+ + "brightness threshold array have different length: "
+ + "displayBrightnessThresholds="
+ + Arrays.toString(mHighDisplayBrightnessThresholds)
+ + ", ambientBrightnessThresholds="
+ + Arrays.toString(mHighAmbientBrightnessThresholds));
+ }
+ mRefreshRateInHighZone = context.getResources().getInteger(
+ R.integer.config_fixedRefreshRateInHighZone);
+ }
+
+ /**
+ * @return the refresh to lock to when in a low brightness zone
+ */
+ @VisibleForTesting
+ int getRefreshRateInLowZone() {
+ return mRefreshRateInLowZone;
+ }
+
+ /**
+ * @return the display brightness thresholds for the low brightness zones
+ */
+ @VisibleForTesting
+ int[] getLowDisplayBrightnessThresholds() {
+ return mLowDisplayBrightnessThresholds;
+ }
+
+ /**
+ * @return the ambient brightness thresholds for the low brightness zones
+ */
+ @VisibleForTesting
+ int[] getLowAmbientBrightnessThresholds() {
+ return mLowAmbientBrightnessThresholds;
+ }
+
+ public void registerLightSensor(SensorManager sensorManager, Sensor lightSensor) {
+ mSensorManager = sensorManager;
+ mLightSensor = lightSensor;
+
+ mSensorManager.registerListener(mLightSensorListener,
+ mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
}
public void observe(SensorManager sensorManager) {
mSensorManager = sensorManager;
+ final ContentResolver cr = mContext.getContentResolver();
+ mBrightness = Settings.System.getIntForUser(cr,
+ Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
// DeviceConfig is accessible after system ready.
- int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
- int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
+ int[] lowDisplayBrightnessThresholds =
+ mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds();
+ int[] lowAmbientBrightnessThresholds =
+ mDeviceConfigDisplaySettings.getLowAmbientBrightnessThresholds();
+
+ if (lowDisplayBrightnessThresholds != null && lowAmbientBrightnessThresholds != null
+ && lowDisplayBrightnessThresholds.length
+ == lowAmbientBrightnessThresholds.length) {
+ mLowDisplayBrightnessThresholds = lowDisplayBrightnessThresholds;
+ mLowAmbientBrightnessThresholds = lowAmbientBrightnessThresholds;
+ }
- if (brightnessThresholds != null && ambientThresholds != null
- && brightnessThresholds.length == ambientThresholds.length) {
- mDisplayBrightnessThresholds = brightnessThresholds;
- mAmbientBrightnessThresholds = ambientThresholds;
+
+ int[] highDisplayBrightnessThresholds =
+ mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds();
+ int[] highAmbientBrightnessThresholds =
+ mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds();
+
+ if (highDisplayBrightnessThresholds != null && highAmbientBrightnessThresholds != null
+ && highDisplayBrightnessThresholds.length
+ == highAmbientBrightnessThresholds.length) {
+ mHighDisplayBrightnessThresholds = highDisplayBrightnessThresholds;
+ mHighAmbientBrightnessThresholds = highAmbientBrightnessThresholds;
}
- mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
+ mRefreshRateInLowZone = mDeviceConfigDisplaySettings.getRefreshRateInLowZone();
+ mRefreshRateInHighZone = mDeviceConfigDisplaySettings.getRefreshRateInHighZone();
+
restartObserver();
mDeviceConfigDisplaySettings.startListening();
}
@@ -1137,7 +1278,7 @@ public class DisplayModeDirector {
updateSensorStatus();
if (!changeable) {
// Revoke previous vote from BrightnessObserver
- updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, null);
+ updateVoteLocked(Vote.PRIORITY_FLICKER, null);
}
}
}
@@ -1149,25 +1290,48 @@ public class DisplayModeDirector {
}
}
- public void onDeviceConfigThresholdsChanged(int[] brightnessThresholds,
+ public void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
int[] ambientThresholds) {
- if (brightnessThresholds != null && ambientThresholds != null
- && brightnessThresholds.length == ambientThresholds.length) {
- mDisplayBrightnessThresholds = brightnessThresholds;
- mAmbientBrightnessThresholds = ambientThresholds;
+ if (displayThresholds != null && ambientThresholds != null
+ && displayThresholds.length == ambientThresholds.length) {
+ mLowDisplayBrightnessThresholds = displayThresholds;
+ mLowAmbientBrightnessThresholds = ambientThresholds;
} else {
// Invalid or empty. Use device default.
- mDisplayBrightnessThresholds = mContext.getResources().getIntArray(
+ mLowDisplayBrightnessThresholds = mContext.getResources().getIntArray(
R.array.config_brightnessThresholdsOfPeakRefreshRate);
- mAmbientBrightnessThresholds = mContext.getResources().getIntArray(
+ mLowAmbientBrightnessThresholds = mContext.getResources().getIntArray(
R.array.config_ambientThresholdsOfPeakRefreshRate);
}
restartObserver();
}
- public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) {
- if (refreshRate != mRefreshRateInZone) {
- mRefreshRateInZone = refreshRate;
+ public void onDeviceConfigRefreshRateInLowZoneChanged(int refreshRate) {
+ if (refreshRate != mRefreshRateInLowZone) {
+ mRefreshRateInLowZone = refreshRate;
+ restartObserver();
+ }
+ }
+
+ public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
+ int[] ambientThresholds) {
+ if (displayThresholds != null && ambientThresholds != null
+ && displayThresholds.length == ambientThresholds.length) {
+ mHighDisplayBrightnessThresholds = displayThresholds;
+ mHighAmbientBrightnessThresholds = ambientThresholds;
+ } else {
+ // Invalid or empty. Use device default.
+ mHighDisplayBrightnessThresholds = mContext.getResources().getIntArray(
+ R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
+ mHighAmbientBrightnessThresholds = mContext.getResources().getIntArray(
+ R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
+ }
+ restartObserver();
+ }
+
+ public void onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate) {
+ if (refreshRate != mRefreshRateInHighZone) {
+ mRefreshRateInHighZone = refreshRate;
restartObserver();
}
}
@@ -1175,48 +1339,95 @@ public class DisplayModeDirector {
public void dumpLocked(PrintWriter pw) {
pw.println(" BrightnessObserver");
pw.println(" mAmbientLux: " + mAmbientLux);
- pw.println(" mRefreshRateInZone: " + mRefreshRateInZone);
+ pw.println(" mBrightness: " + mBrightness);
+ pw.println(" mDefaultDisplayOn: " + mDefaultDisplayOn);
+ pw.println(" mLowPowerModeEnabled: " + mLowPowerModeEnabled);
+ pw.println(" mRefreshRateChangeable: " + mRefreshRateChangeable);
+ pw.println(" mShouldObserveDisplayLowChange: " + mShouldObserveDisplayLowChange);
+ pw.println(" mShouldObserveAmbientLowChange: " + mShouldObserveAmbientLowChange);
+ pw.println(" mRefreshRateInLowZone: " + mRefreshRateInLowZone);
- for (int d: mDisplayBrightnessThresholds) {
- pw.println(" mDisplayBrightnessThreshold: " + d);
+ for (int d : mLowDisplayBrightnessThresholds) {
+ pw.println(" mDisplayLowBrightnessThreshold: " + d);
}
- for (int d: mAmbientBrightnessThresholds) {
- pw.println(" mAmbientBrightnessThreshold: " + d);
+ for (int d : mLowAmbientBrightnessThresholds) {
+ pw.println(" mAmbientLowBrightnessThreshold: " + d);
+ }
+
+ pw.println(" mShouldObserveDisplayHighChange: " + mShouldObserveDisplayHighChange);
+ pw.println(" mShouldObserveAmbientHighChange: " + mShouldObserveAmbientHighChange);
+ pw.println(" mRefreshRateInHighZone: " + mRefreshRateInHighZone);
+
+ for (int d : mHighDisplayBrightnessThresholds) {
+ pw.println(" mDisplayHighBrightnessThresholds: " + d);
+ }
+
+ for (int d : mHighAmbientBrightnessThresholds) {
+ pw.println(" mAmbientHighBrightnessThresholds: " + d);
}
mLightSensorListener.dumpLocked(pw);
+
+ if (mAmbientFilter != null) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.setIndent(" ");
+ mAmbientFilter.dump(ipw);
+ }
}
public void onDisplayChanged(int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
- onScreenOn(isDefaultDisplayOn());
+ updateDefaultDisplayState();
}
}
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
synchronized (mLock) {
- onBrightnessChangedLocked();
+ final ContentResolver cr = mContext.getContentResolver();
+ int brightness = Settings.System.getIntForUser(cr,
+ Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
+ if (brightness != mBrightness) {
+ mBrightness = brightness;
+ onBrightnessChangedLocked();
+ }
}
}
private void restartObserver() {
- mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
- mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
-
final ContentResolver cr = mContext.getContentResolver();
- if (mShouldObserveDisplayChange) {
+
+ if (mRefreshRateInLowZone > 0) {
+ mShouldObserveDisplayLowChange = hasValidThreshold(
+ mLowDisplayBrightnessThresholds);
+ mShouldObserveAmbientLowChange = hasValidThreshold(
+ mLowAmbientBrightnessThresholds);
+ } else {
+ mShouldObserveDisplayLowChange = false;
+ mShouldObserveAmbientLowChange = false;
+ }
+
+ if (mRefreshRateInHighZone > 0) {
+ mShouldObserveDisplayHighChange = hasValidThreshold(
+ mHighDisplayBrightnessThresholds);
+ mShouldObserveAmbientHighChange = hasValidThreshold(
+ mHighAmbientBrightnessThresholds);
+ } else {
+ mShouldObserveDisplayHighChange = false;
+ mShouldObserveAmbientHighChange = false;
+ }
+
+ if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) {
// Content Service does not check if an listener has already been registered.
// To ensure only one listener is registered, force an unregistration first.
- cr.unregisterContentObserver(this);
- cr.registerContentObserver(mDisplayBrightnessSetting,
- false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
+ mInjector.unregisterBrightnessObserver(cr, this);
+ mInjector.registerBrightnessObserver(cr, this);
} else {
- cr.unregisterContentObserver(this);
+ mInjector.unregisterBrightnessObserver(cr, this);
}
- if (mShouldObserveAmbientChange) {
+ if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
Resources resources = mContext.getResources();
String lightSensorType = resources.getString(
com.android.internal.R.string.config_displayLightSensorType);
@@ -1242,8 +1453,6 @@ public class DisplayModeDirector {
mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
mLightSensor = lightSensor;
-
- onScreenOn(isDefaultDisplayOn());
}
} else {
mAmbientFilter = null;
@@ -1262,11 +1471,7 @@ public class DisplayModeDirector {
* Checks to see if at least one value is positive, in which case it is necessary to listen
* to value changes.
*/
- private boolean checkShouldObserve(int[] a) {
- if (mRefreshRateInZone <= 0) {
- return false;
- }
-
+ private boolean hasValidThreshold(int[] a) {
for (int d: a) {
if (d >= 0) {
return true;
@@ -1276,13 +1481,13 @@ public class DisplayModeDirector {
return false;
}
- private boolean isInsideZone(int brightness, float lux) {
- for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
- int disp = mDisplayBrightnessThresholds[i];
- int ambi = mAmbientBrightnessThresholds[i];
+ private boolean isInsideLowZone(int brightness, float lux) {
+ for (int i = 0; i < mLowDisplayBrightnessThresholds.length; i++) {
+ int disp = mLowDisplayBrightnessThresholds[i];
+ int ambi = mLowAmbientBrightnessThresholds[i];
if (disp >= 0 && ambi >= 0) {
- if (brightness <= disp && mAmbientLux <= ambi) {
+ if (brightness <= disp && lux <= ambi) {
return true;
}
} else if (disp >= 0) {
@@ -1290,7 +1495,7 @@ public class DisplayModeDirector {
return true;
}
} else if (ambi >= 0) {
- if (mAmbientLux <= ambi) {
+ if (lux <= ambi) {
return true;
}
}
@@ -1298,27 +1503,77 @@ public class DisplayModeDirector {
return false;
}
- // TODO: brightnessfloat: make it use float not int
- private void onBrightnessChangedLocked() {
- int brightness = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, -1);
+ private boolean isInsideHighZone(int brightness, float lux) {
+ for (int i = 0; i < mHighDisplayBrightnessThresholds.length; i++) {
+ int disp = mHighDisplayBrightnessThresholds[i];
+ int ambi = mHighAmbientBrightnessThresholds[i];
+
+ if (disp >= 0 && ambi >= 0) {
+ if (brightness >= disp && lux >= ambi) {
+ return true;
+ }
+ } else if (disp >= 0) {
+ if (brightness >= disp) {
+ return true;
+ }
+ } else if (ambi >= 0) {
+ if (lux >= ambi) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ private void onBrightnessChangedLocked() {
Vote vote = null;
- boolean insideZone = isInsideZone(brightness, mAmbientLux);
- if (insideZone) {
- vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone);
+
+ if (mBrightness < 0) {
+ // Either the setting isn't available or we shouldn't be observing yet anyways.
+ // Either way, just bail out since there's nothing we can do here.
+ return;
+ }
+
+ boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux);
+ if (insideLowZone) {
+ vote = Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
+ }
+
+ boolean insideHighZone = hasValidHighZone()
+ && isInsideHighZone(mBrightness, mAmbientLux);
+ if (insideHighZone) {
+ vote = Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
}
if (DEBUG) {
- Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " + mAmbientLux +
- ", Vote " + vote);
+ Slog.d(TAG, "Display brightness " + mBrightness + ", ambient lux " + mAmbientLux
+ + ", Vote " + vote);
}
- updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
+ updateVoteLocked(Vote.PRIORITY_FLICKER, vote);
+ }
+
+ private boolean hasValidLowZone() {
+ return mRefreshRateInLowZone > 0
+ && (mShouldObserveDisplayLowChange || mShouldObserveAmbientLowChange);
+ }
+
+ private boolean hasValidHighZone() {
+ return mRefreshRateInHighZone > 0
+ && (mShouldObserveDisplayHighChange || mShouldObserveAmbientHighChange);
}
- private void onScreenOn(boolean on) {
- if (mScreenOn != on) {
- mScreenOn = on;
+ private void updateDefaultDisplayState() {
+ Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ boolean defaultDisplayOn = display != null && display.getState() != Display.STATE_OFF;
+ setDefaultDisplayState(defaultDisplayOn);
+ }
+
+ @VisibleForTesting
+ public void setDefaultDisplayState(boolean on) {
+ if (mDefaultDisplayOn != on) {
+ mDefaultDisplayOn = on;
updateSensorStatus();
}
}
@@ -1328,8 +1583,8 @@ public class DisplayModeDirector {
return;
}
- if (mShouldObserveAmbientChange && mScreenOn && !mLowPowerModeEnabled
- && mRefreshRateChangeable) {
+ if ((mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange)
+ && isDeviceActive() && !mLowPowerModeEnabled && mRefreshRateChangeable) {
mSensorManager.registerListener(mLightSensorListener,
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
} else {
@@ -1338,11 +1593,8 @@ public class DisplayModeDirector {
}
}
- private boolean isDefaultDisplayOn() {
- final Display display = mContext.getSystemService(DisplayManager.class)
- .getDisplay(Display.DEFAULT_DISPLAY);
- return display.getState() != Display.STATE_OFF
- && mContext.getSystemService(PowerManager.class).isInteractive();
+ private boolean isDeviceActive() {
+ return mDefaultDisplayOn && mInjector.isDeviceInteractive(mContext);
}
private final class LightSensorEventListener implements SensorEventListener {
@@ -1360,23 +1612,33 @@ public class DisplayModeDirector {
Slog.d(TAG, "On sensor changed: " + mLastSensorData);
}
- boolean zoneChanged = isDifferentZone(mLastSensorData, mAmbientLux);
- if (zoneChanged && mLastSensorData < mAmbientLux) {
- // Easier to see flicker at lower brightness environment. Forget the history to
- // get immediate response.
- mAmbientFilter.clear();
+ boolean lowZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux,
+ mLowAmbientBrightnessThresholds);
+ boolean highZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux,
+ mHighAmbientBrightnessThresholds);
+ if ((lowZoneChanged && mLastSensorData < mAmbientLux)
+ || (highZoneChanged && mLastSensorData > mAmbientLux)) {
+ // Easier to see flicker at lower brightness environment or high brightness
+ // environment. Forget the history to get immediate response.
+ if (mAmbientFilter != null) {
+ mAmbientFilter.clear();
+ }
}
long now = SystemClock.uptimeMillis();
- mAmbientFilter.addValue(now, mLastSensorData);
+ if (mAmbientFilter != null) {
+ mAmbientFilter.addValue(now, mLastSensorData);
+ }
mHandler.removeCallbacks(mInjectSensorEventRunnable);
processSensorData(now);
- if (zoneChanged && mLastSensorData > mAmbientLux) {
+ if ((lowZoneChanged && mLastSensorData > mAmbientLux)
+ || (highZoneChanged && mLastSensorData < mAmbientLux)) {
// Sensor may not report new event if there is no brightness change.
// Need to keep querying the temporal filter for the latest estimation,
- // until enter in higher lux zone or is interrupted by a new sensor event.
+ // until sensor readout and filter estimation are in the same zone or
+ // is interrupted by a new sensor event.
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
}
}
@@ -1391,17 +1653,19 @@ public class DisplayModeDirector {
}
private void processSensorData(long now) {
- mAmbientLux = mAmbientFilter.getEstimate(now);
+ if (mAmbientFilter != null) {
+ mAmbientLux = mAmbientFilter.getEstimate(now);
+ } else {
+ mAmbientLux = mLastSensorData;
+ }
synchronized (mLock) {
onBrightnessChangedLocked();
}
}
- private boolean isDifferentZone(float lux1, float lux2) {
- for (int z = 0; z < mAmbientBrightnessThresholds.length; z++) {
- final float boundary = mAmbientBrightnessThresholds[z];
-
+ private boolean isDifferentZone(float lux1, float lux2, int[] luxThresholds) {
+ for (final float boundary : luxThresholds) {
// Test each boundary. See if the current value and the new value are at
// different sides.
if ((lux1 <= boundary && lux2 > boundary)
@@ -1421,7 +1685,10 @@ public class DisplayModeDirector {
processSensorData(now);
// Inject next event if there is a possible zone change.
- if (isDifferentZone(mLastSensorData, mAmbientLux)) {
+ if (isDifferentZone(mLastSensorData, mAmbientLux,
+ mLowAmbientBrightnessThresholds)
+ || isDifferentZone(mLastSensorData, mAmbientLux,
+ mHighAmbientBrightnessThresholds)) {
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
}
}
@@ -1434,72 +1701,113 @@ public class DisplayModeDirector {
}
public void startListening() {
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
BackgroundThread.getExecutor(), this);
}
/*
* Return null if no such property or wrong format (not comma separated integers).
*/
- public int[] getBrightnessThresholds() {
+ public int[] getLowDisplayBrightnessThresholds() {
return getIntArrayProperty(
DisplayManager.DeviceConfig.
- KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
+ KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
}
/*
* Return null if no such property or wrong format (not comma separated integers).
*/
- public int[] getAmbientThresholds() {
+ public int[] getLowAmbientBrightnessThresholds() {
return getIntArrayProperty(
DisplayManager.DeviceConfig.
- KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
+ KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
+ }
+
+ public int getRefreshRateInLowZone() {
+ int defaultRefreshRateInZone = mContext.getResources().getInteger(
+ R.integer.config_defaultRefreshRateInZone);
+
+ int refreshRate = mDeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE,
+ defaultRefreshRateInZone);
+
+ return refreshRate;
}
/*
- * Return null if no such property
+ * Return null if no such property or wrong format (not comma separated integers).
*/
- public Float getDefaultPeakRefreshRate() {
- float defaultPeakRefreshRate = DeviceConfig.getFloat(
- DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
- DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
+ public int[] getHighDisplayBrightnessThresholds() {
+ return getIntArrayProperty(
+ DisplayManager.DeviceConfig
+ .KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS);
+ }
- if (defaultPeakRefreshRate == -1) {
- return null;
- }
- return defaultPeakRefreshRate;
+ /*
+ * Return null if no such property or wrong format (not comma separated integers).
+ */
+ public int[] getHighAmbientBrightnessThresholds() {
+ return getIntArrayProperty(
+ DisplayManager.DeviceConfig
+ .KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS);
}
- public int getRefreshRateInZone() {
+ public int getRefreshRateInHighZone() {
int defaultRefreshRateInZone = mContext.getResources().getInteger(
- R.integer.config_defaultRefreshRateInZone);
+ R.integer.config_fixedRefreshRateInHighZone);
- int refreshRate = DeviceConfig.getInt(
+ int refreshRate = mDeviceConfig.getInt(
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
- DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
+ DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE,
defaultRefreshRateInZone);
return refreshRate;
}
+ /*
+ * Return null if no such property
+ */
+ public Float getDefaultPeakRefreshRate() {
+ float defaultPeakRefreshRate = mDeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
+
+ if (defaultPeakRefreshRate == -1) {
+ return null;
+ }
+ return defaultPeakRefreshRate;
+ }
+
@Override
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
- int[] brightnessThresholds = getBrightnessThresholds();
- int[] ambientThresholds = getAmbientThresholds();
Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
- int refreshRateInZone = getRefreshRateInZone();
-
- mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
- new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
- .sendToTarget();
mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
defaultPeakRefreshRate).sendToTarget();
- mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone,
- 0).sendToTarget();
+
+ int[] lowDisplayBrightnessThresholds = getLowDisplayBrightnessThresholds();
+ int[] lowAmbientBrightnessThresholds = getLowAmbientBrightnessThresholds();
+ int refreshRateInLowZone = getRefreshRateInLowZone();
+
+ mHandler.obtainMessage(MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED,
+ new Pair<>(lowDisplayBrightnessThresholds, lowAmbientBrightnessThresholds))
+ .sendToTarget();
+ mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone, 0)
+ .sendToTarget();
+
+ int[] highDisplayBrightnessThresholds = getHighDisplayBrightnessThresholds();
+ int[] highAmbientBrightnessThresholds = getHighAmbientBrightnessThresholds();
+ int refreshRateInHighZone = getRefreshRateInHighZone();
+
+ mHandler.obtainMessage(MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED,
+ new Pair<>(highDisplayBrightnessThresholds, highAmbientBrightnessThresholds))
+ .sendToTarget();
+ mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
+ .sendToTarget();
}
private int[] getIntArrayProperty(String prop) {
- String strArray = DeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
+ String strArray = mDeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
null);
if (strArray != null) {
@@ -1526,4 +1834,59 @@ public class DisplayModeDirector {
}
}
+ interface Injector {
+ // TODO: brightnessfloat: change this to the float setting
+ Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+ Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
+
+ @NonNull
+ DeviceConfigInterface getDeviceConfig();
+
+ void registerBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer);
+
+ void unregisterBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer);
+
+ void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer);
+
+ boolean isDeviceInteractive(@NonNull Context context);
+ }
+
+ @VisibleForTesting
+ static class RealInjector implements Injector {
+
+ @Override
+ @NonNull
+ public DeviceConfigInterface getDeviceConfig() {
+ return DeviceConfigInterface.REAL;
+ }
+
+ @Override
+ public void registerBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/,
+ observer, UserHandle.USER_SYSTEM);
+ }
+
+ @Override
+ public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ cr.unregisterContentObserver(observer);
+ }
+
+ @Override
+ public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/,
+ observer, UserHandle.USER_SYSTEM);
+ }
+
+ @Override
+ public boolean isDeviceInteractive(@NonNull Context ctx) {
+ return ctx.getSystemService(PowerManager.class).isInteractive();
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b6fbedb76e15..75fa9ebf693f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3274,9 +3274,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
- if (mCurClient == null || mCurClient.curSession == null) {
- return false;
- }
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 5c9350a8452c..3bb55a5af5c6 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -906,9 +906,26 @@ public class LocationManagerService extends ILocationManager.Stub {
if (enabled == null) {
// this generally shouldn't occur, but might be possible due to race conditions
// on when we are notified of new users
+
+ // hack to fix b/171910679. mutating the user enabled state within this method
+ // may cause unexpected changes to other state (for instance, this could cause
+ // provider enable/disable notifications to be sent to clients, which could
+ // result in a dead client being detected, which could result in the client
+ // being removed, which means that if this function is called while clients are
+ // being iterated over we have now unexpectedly mutated the iterated
+ // collection). instead, we return a correct value immediately here, and
+ // schedule the actual update for later. this has been completely rewritten and
+ // is no longer a problem in the next version of android.
+ enabled = mProvider.getState().allowed
+ && mUserInfoHelper.isCurrentUserId(userId)
+ && mSettingsHelper.isLocationEnabled(userId);
+
Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly");
- onEnabledChangedLocked(userId);
- enabled = Objects.requireNonNull(mEnabled.get(userId));
+ mHandler.post(() -> {
+ synchronized (mLock) {
+ onEnabledChangedLocked(userId);
+ }
+ });
}
return enabled;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 61f5fb878b3b..d003b89e8877 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -113,6 +113,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;
@@ -2629,6 +2630,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);
if (auth == null) {
@@ -2689,7 +2694,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,
diff --git a/services/core/java/com/android/server/notification/InjectableSystemClock.java b/services/core/java/com/android/server/notification/InjectableSystemClock.java
new file mode 100644
index 000000000000..4d993d19e57b
--- /dev/null
+++ b/services/core/java/com/android/server/notification/InjectableSystemClock.java
@@ -0,0 +1,44 @@
+/*
+ * 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.notification;
+
+/**
+ * Testable wrapper around {@link android.os.SystemClock}.
+ *
+ * The default implementation at InjectableSystemClockImpl just proxies calls to the real
+ * SystemClock
+ *
+ * In tests, pass an instance of FakeSystemClock, which allows you to control the values returned by
+ * the various getters below.
+ */
+public interface InjectableSystemClock {
+ /** @see android.os.SystemClock#uptimeMillis() */
+ long uptimeMillis();
+
+ /** @see android.os.SystemClock#elapsedRealtime() */
+ long elapsedRealtime();
+
+ /** @see android.os.SystemClock#elapsedRealtimeNanos() */
+ long elapsedRealtimeNanos();
+
+ /** @see android.os.SystemClock#currentThreadTimeMillis() */
+ long currentThreadTimeMillis();
+
+ /** @see System#currentTimeMillis() */
+ long currentTimeMillis();
+}
+
diff --git a/services/core/java/com/android/server/notification/InjectableSystemClockImpl.java b/services/core/java/com/android/server/notification/InjectableSystemClockImpl.java
new file mode 100644
index 000000000000..43d756f46176
--- /dev/null
+++ b/services/core/java/com/android/server/notification/InjectableSystemClockImpl.java
@@ -0,0 +1,51 @@
+/*
+ * 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.notification;
+
+/**
+ * Default implementation of {@link InjectableSystemClock}.
+ *
+ * @hide
+ */
+public class InjectableSystemClockImpl implements InjectableSystemClock {
+ public InjectableSystemClockImpl() {}
+
+ @Override
+ public long uptimeMillis() {
+ return android.os.SystemClock.uptimeMillis();
+ }
+
+ @Override
+ public long elapsedRealtime() {
+ return android.os.SystemClock.elapsedRealtime();
+ }
+
+ @Override
+ public long elapsedRealtimeNanos() {
+ return android.os.SystemClock.elapsedRealtimeNanos();
+ }
+
+ @Override
+ public long currentThreadTimeMillis() {
+ return android.os.SystemClock.currentThreadTimeMillis();
+ }
+
+ @Override
+ public long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5ddb6e1b04f6..346be75d3d3d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -59,6 +59,7 @@ import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.media.AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -186,7 +187,6 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
@@ -472,6 +472,11 @@ public class NotificationManagerService extends SystemService {
final ArrayMap<Integer, ArrayMap<String, String>> mAutobundledSummaries = new ArrayMap<>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
+ // Keep track of `CancelNotificationRunnable`s which have been delayed due to awaiting
+ // enqueued notifications to post
+ @GuardedBy("mNotificationLock")
+ final ArrayMap<NotificationRecord, ArrayList<CancelNotificationRunnable>> mDelayedCancelations =
+ new ArrayMap<>();
// The last key in this list owns the hardware.
ArrayList<String> mLights = new ArrayList<>();
@@ -534,6 +539,7 @@ public class NotificationManagerService extends SystemService {
private NotificationRecordLogger mNotificationRecordLogger;
private InstanceIdSequence mNotificationInstanceIdSequence;
private Set<String> mMsgPkgsAllowedAsConvos = new HashSet();
+ private final InjectableSystemClock mSystemClock;
static class Archive {
final SparseArray<Boolean> mEnabled;
@@ -747,7 +753,7 @@ public class NotificationManagerService extends SystemService {
parser, mAllowedManagedServicePackages, forRestore, userId);
migratedManagedServices = true;
} else if (mSnoozeHelper.XML_TAG_NAME.equals(parser.getName())) {
- mSnoozeHelper.readXml(parser, System.currentTimeMillis());
+ mSnoozeHelper.readXml(parser, mSystemClock.currentTimeMillis());
}
if (LOCKSCREEN_ALLOW_SECURE_NOTIFICATIONS_TAG.equals(parser.getName())) {
if (forRestore && userId != UserHandle.USER_SYSTEM) {
@@ -900,7 +906,7 @@ public class NotificationManagerService extends SystemService {
Slog.w(TAG, "No notification with key: " + key);
return;
}
- final long now = System.currentTimeMillis();
+ final long now = mSystemClock.currentTimeMillis();
MetricsLogger.action(r.getItemLogMaker()
.setType(MetricsEvent.TYPE_ACTION)
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
@@ -932,7 +938,7 @@ public class NotificationManagerService extends SystemService {
Slog.w(TAG, "No notification with key: " + key);
return;
}
- final long now = System.currentTimeMillis();
+ final long now = mSystemClock.currentTimeMillis();
MetricsLogger.action(r.getLogMaker(now)
.setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
.setType(MetricsEvent.TYPE_ACTION)
@@ -1696,15 +1702,18 @@ public class NotificationManagerService extends SystemService {
public NotificationManagerService(Context context) {
this(context,
new NotificationRecordLoggerImpl(),
+ new InjectableSystemClockImpl(),
new InstanceIdSequence(NOTIFICATION_INSTANCE_ID_MAX));
}
@VisibleForTesting
public NotificationManagerService(Context context,
NotificationRecordLogger notificationRecordLogger,
+ InjectableSystemClock systemClock,
InstanceIdSequence notificationInstanceIdSequence) {
super(context);
mNotificationRecordLogger = notificationRecordLogger;
+ mSystemClock = systemClock;
mNotificationInstanceIdSequence = notificationInstanceIdSequence;
Notification.processAllowlistToken = ALLOWLIST_TOKEN;
}
@@ -2063,6 +2072,11 @@ public class NotificationManagerService extends SystemService {
return getContext().getResources().getStringArray(key);
}
+ @VisibleForTesting
+ protected Handler getWorkHandler() {
+ return mHandler;
+ }
+
@Override
public void onStart() {
SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), (userId, r, muteOnReturn) -> {
@@ -2336,7 +2350,8 @@ public class NotificationManagerService extends SystemService {
mHistoryManager.onBootPhaseAppsCanStart();
registerDeviceConfigChange();
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
- mSnoozeHelper.scheduleRepostsForPersistedNotifications(System.currentTimeMillis());
+ mSnoozeHelper.scheduleRepostsForPersistedNotifications(
+ mSystemClock.currentTimeMillis());
}
}
@@ -2696,7 +2711,7 @@ public class NotificationManagerService extends SystemService {
.setUserId(r.getSbn().getNormalizedUserId())
.setChannelId(r.getChannel().getId())
.setChannelName(r.getChannel().getName().toString())
- .setPostedTimeMs(System.currentTimeMillis())
+ .setPostedTimeMs(mSystemClock.currentTimeMillis())
.setTitle(getHistoryTitle(r.getNotification()))
.setText(getHistoryText(
r.getSbn().getPackageContext(getContext()), r.getNotification()))
@@ -3056,6 +3071,8 @@ public class NotificationManagerService extends SystemService {
UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
}
+ mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
+ enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
try {
getContext().sendBroadcastAsUser(
new Intent(ACTION_APP_BLOCK_STATE_CHANGED)
@@ -3517,8 +3534,9 @@ public class NotificationManagerService extends SystemService {
public ParceledListSlice<ConversationChannelWrapper> getConversations(
boolean onlyImportant) {
enforceSystemOrSystemUI("getConversations");
+ IntArray userIds = mUserProfiles.getCurrentProfileIds();
ArrayList<ConversationChannelWrapper> conversations =
- mPreferencesHelper.getConversations(onlyImportant);
+ mPreferencesHelper.getConversations(userIds, onlyImportant);
for (ConversationChannelWrapper conversation : conversations) {
if (mShortcutHelper == null) {
conversation.setShortcutInfo(null);
@@ -5222,7 +5240,7 @@ public class NotificationManagerService extends SystemService {
GroupHelper.AUTOGROUP_KEY, adjustedSbn.getUid(),
adjustedSbn.getInitialPid(), summaryNotification,
adjustedSbn.getUser(), GroupHelper.AUTOGROUP_KEY,
- System.currentTimeMillis());
+ mSystemClock.currentTimeMillis());
summaryRecord = new NotificationRecord(getContext(), summarySbn,
notificationRecord.getChannel());
summaryRecord.setIsAppImportanceLocked(
@@ -5457,6 +5475,22 @@ public class NotificationManagerService extends SystemService {
mSnoozeHelper.dump(pw, filter);
}
+
+ // Log delayed notification cancels
+ pw.println();
+ pw.println(" Delayed notification cancels:");
+ if (mDelayedCancelations.isEmpty()) {
+ pw.println(" None");
+ } else {
+ Set<NotificationRecord> delayedKeys = mDelayedCancelations.keySet();
+ for (NotificationRecord record : delayedKeys) {
+ ArrayList<CancelNotificationRunnable> queuedCancels =
+ mDelayedCancelations.get(record);
+ pw.println(" (" + queuedCancels.size() + ") cancels enqueued for"
+ + record.getKey());
+ }
+ }
+ pw.println();
}
if (!zenOnly) {
@@ -5675,7 +5709,7 @@ public class NotificationManagerService extends SystemService {
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, notificationUid, callingPid, notification,
- user, null, System.currentTimeMillis());
+ user, null, mSystemClock.currentTimeMillis());
// setup local book-keeping
String channelId = notification.getChannelId();
@@ -6008,7 +6042,7 @@ public class NotificationManagerService extends SystemService {
final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
if (appEnqueueRate > mMaxPackageEnqueueRate) {
mUsageStats.registerOverRateQuota(pkg);
- final long now = SystemClock.elapsedRealtime();
+ final long now = mSystemClock.elapsedRealtime();
if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
+ ". Shedding " + r.getSbn().getKey() + ". package=" + pkg);
@@ -6220,7 +6254,73 @@ public class NotificationManagerService extends SystemService {
this.mRank = rank;
this.mCount = count;
this.mListener = listener;
- this.mWhen = System.currentTimeMillis();
+ this.mWhen = mSystemClock.currentTimeMillis();
+ }
+
+ // Move the work to this function so it can be called from PostNotificationRunnable
+ private void doNotificationCancelLocked() {
+ // Look for the notification in the posted list, since we already checked enqueued.
+ String listenerName = mListener == null ? null : mListener.component.toShortString();
+ NotificationRecord r =
+ findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId);
+ if (r != null) {
+ // The notification was found, check if it should be removed.
+
+ // Ideally we'd do this in the caller of this method. However, that would
+ // require the caller to also find the notification.
+ if (mReason == REASON_CLICK) {
+ mUsageStats.registerClickedByUser(r);
+ }
+
+ if (mReason == REASON_LISTENER_CANCEL
+ && (r.getNotification().flags & FLAG_BUBBLE) != 0) {
+ mNotificationDelegate.onBubbleNotificationSuppressionChanged(
+ r.getKey(), /* suppressed */ true);
+ return;
+ }
+
+ if ((r.getNotification().flags & mMustHaveFlags) != mMustHaveFlags) {
+ return;
+ }
+ if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
+ return;
+ }
+
+ // Bubbled children get to stick around if the summary was manually cancelled
+ // (user removed) from systemui.
+ FlagChecker childrenFlagChecker = null;
+ if (mReason == REASON_CANCEL
+ || mReason == REASON_CLICK
+ || mReason == REASON_CANCEL_ALL) {
+ childrenFlagChecker = (flags) -> {
+ if ((flags & FLAG_BUBBLE) != 0) {
+ return false;
+ }
+ return true;
+ };
+ }
+
+ // Cancel the notification.
+ boolean wasPosted = removePreviousFromNotificationListsLocked(r, mWhen);
+ cancelNotificationLocked(
+ r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
+ cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
+ mSendDelete, childrenFlagChecker, mReason);
+ updateLightsLocked();
+ if (mShortcutHelper != null) {
+ mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
+ true /* isRemoved */,
+ mHandler);
+ }
+ } else {
+ // No notification was found, assume that it is snoozed and cancel it.
+ if (mReason != REASON_SNOOZED) {
+ final boolean wasSnoozed = mSnoozeHelper.cancel(mUserId, mPkg, mTag, mId);
+ if (wasSnoozed) {
+ handleSavePolicyFile();
+ }
+ }
+ }
}
@Override
@@ -6236,91 +6336,24 @@ public class NotificationManagerService extends SystemService {
// chance to post yet.
List<NotificationRecord> enqueued = findEnqueuedNotificationsForCriteria(
mPkg, mTag, mId, mUserId);
- boolean repost = false;
if (enqueued.size() > 0) {
- // Found something, let's see what it was
- repost = true;
- // If all enqueues happened before this cancel then wait for them to happen,
- // otherwise we should let this cancel through so the next enqueue happens
- for (NotificationRecord r : enqueued) {
- if (r.mUpdateTimeMs > mWhen) {
- // At least one enqueue was posted after the cancel, so we're invalid
- Slog.i(TAG, "notification cancel ignored due to newer enqueued entry"
- + "key=" + r.getSbn().getKey());
- return;
- }
+ // We have found notifications that were enqueued before this cancel, but not
+ // yet posted. Attach this cancel to the last enqueue (the most recent), and
+ // we will be executed in that notification's PostNotificationRunnable
+ NotificationRecord enqueuedToAttach = enqueued.get(enqueued.size() - 1);
+
+ ArrayList<CancelNotificationRunnable> delayed =
+ mDelayedCancelations.get(enqueuedToAttach);
+ if (delayed == null) {
+ delayed = new ArrayList<>();
}
- }
- if (repost) {
- mHandler.post(this);
+
+ delayed.add(this);
+ mDelayedCancelations.put(enqueuedToAttach, delayed);
return;
}
- // Look for the notification in the posted list, since we already checked enqueued.
- NotificationRecord r =
- findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId);
- if (r != null) {
- // The notification was found, check if it should be removed.
-
- // Ideally we'd do this in the caller of this method. However, that would
- // require the caller to also find the notification.
- if (mReason == REASON_CLICK) {
- mUsageStats.registerClickedByUser(r);
- }
-
- if (mReason == REASON_LISTENER_CANCEL
- && (r.getNotification().flags & FLAG_BUBBLE) != 0) {
- mNotificationDelegate.onBubbleNotificationSuppressionChanged(
- r.getKey(), /* suppressed */ true);
- return;
- }
-
- if ((r.getNotification().flags & mMustHaveFlags) != mMustHaveFlags) {
- return;
- }
- if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
- return;
- }
- if (r.getUpdateTimeMs() > mWhen) {
- // In this case, a post must have slipped by when this runnable reposted
- return;
- }
-
- // Bubbled children get to stick around if the summary was manually cancelled
- // (user removed) from systemui.
- FlagChecker childrenFlagChecker = null;
- if (mReason == REASON_CANCEL
- || mReason == REASON_CLICK
- || mReason == REASON_CANCEL_ALL) {
- childrenFlagChecker = (flags) -> {
- if ((flags & FLAG_BUBBLE) != 0) {
- return false;
- }
- return true;
- };
- }
-
- // Cancel the notification.
- boolean wasPosted = removeFromNotificationListsLocked(r);
- cancelNotificationLocked(
- r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
- cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
- mSendDelete, childrenFlagChecker, mReason);
- updateLightsLocked();
- if (mShortcutHelper != null) {
- mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
- true /* isRemoved */,
- mHandler);
- }
- } else {
- // No notification was found, assume that it is snoozed and cancel it.
- if (mReason != REASON_SNOOZED) {
- final boolean wasSnoozed = mSnoozeHelper.cancel(mUserId, mPkg, mTag, mId);
- if (wasSnoozed) {
- handleSavePolicyFile();
- }
- }
- }
+ doNotificationCancelLocked();
}
}
}
@@ -6343,7 +6376,7 @@ public class NotificationManagerService extends SystemService {
mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
r.getUser().getIdentifier(),
r.getSbn().getPackageName(), r.getSbn().getKey());
- final long currentTime = System.currentTimeMillis();
+ final long currentTime = mSystemClock.currentTimeMillis();
if (snoozeAt.longValue() > currentTime) {
(new SnoozeNotificationRunnable(r.getSbn().getKey(),
snoozeAt.longValue() - currentTime, null)).snoozeLocked(r);
@@ -6403,18 +6436,29 @@ public class NotificationManagerService extends SystemService {
enqueueStatus);
}
- // tell the assistant service about the notification
- if (mAssistants.isEnabled()) {
- mAssistants.onNotificationEnqueuedLocked(r);
- mHandler.postDelayed(new PostNotificationRunnable(r.getKey()),
- DELAY_FOR_ASSISTANT_TIME);
- } else {
- mHandler.post(new PostNotificationRunnable(r.getKey()));
- }
+ postPostNotificationRunnableMaybeDelayedLocked(
+ r, new PostNotificationRunnable(r.getKey()));
}
}
}
+ /**
+ * Mainly needed as a hook for tests which require setting up enqueued-but-not-posted
+ * notification records
+ */
+ @GuardedBy("mNotificationLock")
+ protected void postPostNotificationRunnableMaybeDelayedLocked(
+ NotificationRecord r,
+ PostNotificationRunnable runnable) {
+ // tell the assistant service about the notification
+ if (mAssistants.isEnabled()) {
+ mAssistants.onNotificationEnqueuedLocked(r);
+ mHandler.postDelayed(runnable, DELAY_FOR_ASSISTANT_TIME);
+ } else {
+ mHandler.post(runnable);
+ }
+ }
+
@GuardedBy("mNotificationLock")
boolean isPackagePausedOrSuspended(String pkg, int uid) {
boolean isPaused;
@@ -6563,13 +6607,23 @@ public class NotificationManagerService extends SystemService {
buzzBeepBlinkLoggingCode, getGroupInstanceId(n.getGroupKey()));
} finally {
int N = mEnqueuedNotifications.size();
+ NotificationRecord enqueued = null;
for (int i = 0; i < N; i++) {
- final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
+ enqueued = mEnqueuedNotifications.get(i);
if (Objects.equals(key, enqueued.getKey())) {
mEnqueuedNotifications.remove(i);
break;
}
}
+
+ // If the enqueued notification record had a cancel attached after it, execute
+ // it right now
+ if (enqueued != null && mDelayedCancelations.get(enqueued) != null) {
+ for (CancelNotificationRunnable r : mDelayedCancelations.get(enqueued)) {
+ r.doNotificationCancelLocked();
+ }
+ mDelayedCancelations.remove(enqueued);
+ }
}
}
}
@@ -6798,7 +6852,8 @@ public class NotificationManagerService extends SystemService {
.putExtra(EXTRA_KEY, record.getKey()),
PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + record.getNotification().getTimeoutAfter(), pi);
+ mSystemClock.elapsedRealtime() + record.getNotification().getTimeoutAfter(),
+ pi);
}
}
@@ -7102,8 +7157,15 @@ public class NotificationManagerService extends SystemService {
// so need to check the notification still valide for vibrate.
synchronized (mNotificationLock) {
if (mNotificationsByKey.get(record.getKey()) != null) {
+ // Vibrator checks the appops for the op package, not the caller,
+ // so we need to add the bypass dnd flag to be heard. it's ok to
+ // always add this flag here because we've already checked that we can
+ // bypass dnd
+ AudioAttributes.Builder aab =
+ new AudioAttributes.Builder(record.getAudioAttributes())
+ .setFlags(FLAG_BYPASS_INTERRUPTION_POLICY);
mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getOpPkg(),
- effect, "Notification (delayed)", record.getAudioAttributes());
+ effect, "Notification (delayed)", aab.build());
} else {
Slog.e(TAG, "No vibration for canceled notification : "
+ record.getKey());
@@ -7323,7 +7385,7 @@ public class NotificationManagerService extends SystemService {
|| visibilityChanged
|| interruptiveChanged;
if (interceptBefore && !record.isIntercepted()
- && record.isNewEnoughForAlerting(System.currentTimeMillis())) {
+ && record.isNewEnoughForAlerting(mSystemClock.currentTimeMillis())) {
buzzBeepBlinkLocked(record);
}
}
@@ -7610,6 +7672,34 @@ public class NotificationManagerService extends SystemService {
return wasPosted;
}
+ /**
+ * Similar to the above method, removes all NotificationRecords with the same key as the given
+ * NotificationRecord, but skips any records which are newer than the given one.
+ */
+ private boolean removePreviousFromNotificationListsLocked(NotificationRecord r,
+ long removeBefore) {
+ // Remove notification records that occurred before the given record from both lists,
+ // specifically allowing newer ones to respect ordering
+ boolean wasPosted = false;
+ List<NotificationRecord> matching =
+ findNotificationsByListLocked(mNotificationList, r.getKey());
+ for (NotificationRecord record : matching) {
+ // We don't need to check against update time for posted notifs
+ mNotificationList.remove(record);
+ mNotificationsByKey.remove(record.getSbn().getKey());
+ wasPosted = true;
+ }
+
+ matching = findNotificationsByListLocked(mEnqueuedNotifications, r.getKey());
+ for (NotificationRecord record : matching) {
+ if (record.getUpdateTimeMs() <= removeBefore) {
+ mNotificationList.remove(record);
+ }
+ }
+
+ return wasPosted;
+ }
+
@GuardedBy("mNotificationLock")
private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete,
@NotificationListenerService.NotificationCancelReason int reason,
@@ -7725,7 +7815,7 @@ public class NotificationManagerService extends SystemService {
// Save it for users of getHistoricalNotifications()
mArchive.record(r.getSbn(), reason);
- final long now = System.currentTimeMillis();
+ final long now = mSystemClock.currentTimeMillis();
final LogMaker logMaker = r.getItemLogMaker()
.setType(MetricsEvent.TYPE_DISMISS)
.setSubtype(reason);
@@ -8281,6 +8371,21 @@ public class NotificationManagerService extends SystemService {
return null;
}
+ @GuardedBy("mNotificationLock")
+ private List<NotificationRecord> findNotificationsByListLocked(
+ ArrayList<NotificationRecord> list,
+ String key) {
+ List<NotificationRecord> matching = new ArrayList<>();
+ final int n = list.size();
+ for (int i = 0; i < n; i++) {
+ NotificationRecord r = list.get(i);
+ if (key.equals(r.getKey())) {
+ matching.add(r);
+ }
+ }
+ return matching;
+ }
+
/**
* There may be multiple records that match your criteria. For instance if there have been
* multiple notifications posted which are enqueued for the same pkg, tag, id, userId. This
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index b42fe929549a..9e91875bfd86 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -77,7 +77,6 @@ public class NotificationUsageStats {
private final Map<String, AggregatedStats> mStats = new HashMap<>();
private final ArrayDeque<AggregatedStats[]> mStatsArrays = new ArrayDeque<>();
private ArraySet<String> mStatExpiredkeys = new ArraySet<>();
- private final SQLiteLog mSQLiteLog;
private final Context mContext;
private final Handler mHandler;
private long mLastEmitTime;
@@ -85,7 +84,6 @@ public class NotificationUsageStats {
public NotificationUsageStats(Context context) {
mContext = context;
mLastEmitTime = SystemClock.elapsedRealtime();
- mSQLiteLog = ENABLE_SQLITE_LOG ? new SQLiteLog(context) : null;
mHandler = new Handler(mContext.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -152,9 +150,6 @@ public class NotificationUsageStats {
stats.numUndecoratedRemoteViews += (notification.hasUndecoratedRemoteView() ? 1 : 0);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logPosted(notification);
- }
}
/**
@@ -170,9 +165,6 @@ public class NotificationUsageStats {
stats.countApiUse(notification);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logPosted(notification);
- }
}
/**
@@ -185,9 +177,6 @@ public class NotificationUsageStats {
stats.numRemovedByApp++;
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logRemoved(notification);
- }
}
/**
@@ -197,9 +186,6 @@ public class NotificationUsageStats {
MetricsLogger.histogram(mContext, "note_dismiss_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onDismiss();
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logDismissed(notification);
- }
}
/**
@@ -209,9 +195,6 @@ public class NotificationUsageStats {
MetricsLogger.histogram(mContext, "note_click_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onClick();
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.logClicked(notification);
- }
}
public synchronized void registerPeopleAffinity(NotificationRecord notification, boolean valid,
@@ -328,21 +311,18 @@ public class NotificationUsageStats {
// pass
}
}
- if (ENABLE_SQLITE_LOG) {
- try {
- dump.put("historical", mSQLiteLog.dumpJson(filter));
- } catch (JSONException e) {
- // pass
- }
- }
return dump;
}
public PulledStats remoteViewStats(long startMs, boolean aggregate) {
- if (ENABLE_SQLITE_LOG) {
- if (aggregate) {
- return mSQLiteLog.remoteViewAggStats(startMs);
+ if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
+ PulledStats stats = new PulledStats(startMs);
+ for (AggregatedStats as : mStats.values()) {
+ if (as.numUndecoratedRemoteViews > 0) {
+ stats.addUndecoratedPackage(as.key, as.mCreated);
+ }
}
+ return stats;
}
return null;
}
@@ -357,9 +337,6 @@ public class NotificationUsageStats {
pw.println(indent + "mStatsArrays.size(): " + mStatsArrays.size());
pw.println(indent + "mStats.size(): " + mStats.size());
}
- if (ENABLE_SQLITE_LOG) {
- mSQLiteLog.dump(pw, indent, filter);
- }
}
public synchronized void emit() {
@@ -1046,353 +1023,4 @@ public class NotificationUsageStats {
'}';
}
}
-
- private static class SQLiteLog {
- private static final String TAG = "NotificationSQLiteLog";
-
- // Message types passed to the background handler.
- private static final int MSG_POST = 1;
- private static final int MSG_CLICK = 2;
- private static final int MSG_REMOVE = 3;
- private static final int MSG_DISMISS = 4;
-
- private static final String DB_NAME = "notification_log.db";
- private static final int DB_VERSION = 7;
-
- /** Age in ms after which events are pruned from the DB. */
- private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
- /** Delay between pruning the DB. Used to throttle pruning. */
- private static final long PRUNE_MIN_DELAY_MS = 6 * 60 * 60 * 1000L; // 6 hours
- /** Mininum number of writes between pruning the DB. Used to throttle pruning. */
- private static final long PRUNE_MIN_WRITES = 1024;
-
- // Table 'log'
- private static final String TAB_LOG = "log";
- private static final String COL_EVENT_USER_ID = "event_user_id";
- private static final String COL_EVENT_TYPE = "event_type";
- private static final String COL_EVENT_TIME = "event_time_ms";
- private static final String COL_KEY = "key";
- private static final String COL_PKG = "pkg";
- private static final String COL_NOTIFICATION_ID = "nid";
- private static final String COL_TAG = "tag";
- private static final String COL_WHEN_MS = "when_ms";
- private static final String COL_DEFAULTS = "defaults";
- private static final String COL_FLAGS = "flags";
- private static final String COL_IMPORTANCE_REQ = "importance_request";
- private static final String COL_IMPORTANCE_FINAL = "importance_final";
- private static final String COL_NOISY = "noisy";
- private static final String COL_MUTED = "muted";
- private static final String COL_DEMOTED = "demoted";
- private static final String COL_CATEGORY = "category";
- private static final String COL_ACTION_COUNT = "action_count";
- private static final String COL_POSTTIME_MS = "posttime_ms";
- private static final String COL_AIRTIME_MS = "airtime_ms";
- private static final String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
- private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
- private static final String COL_EXPAND_COUNT = "expansion_count";
- private static final String COL_UNDECORATED = "undecorated";
-
-
- private static final int EVENT_TYPE_POST = 1;
- private static final int EVENT_TYPE_CLICK = 2;
- private static final int EVENT_TYPE_REMOVE = 3;
- private static final int EVENT_TYPE_DISMISS = 4;
-
- private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
-
- private static long sLastPruneMs;
-
- private static long sNumWrites;
- private final SQLiteOpenHelper mHelper;
-
- private final Handler mWriteHandler;
- private static final long DAY_MS = 24 * 60 * 60 * 1000;
- private static final String STATS_QUERY = "SELECT " +
- COL_EVENT_USER_ID + ", " +
- COL_PKG + ", " +
- // Bucket by day by looking at 'floor((midnight - eventTimeMs) / dayMs)'
- "CAST(((%d - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
- "AS day, " +
- "COUNT(*) AS cnt, " +
- "SUM(" + COL_MUTED + ") as muted, " +
- "SUM(" + COL_NOISY + ") as noisy, " +
- "SUM(" + COL_DEMOTED + ") as demoted, " +
- "SUM(" + COL_UNDECORATED + ") as undecorated " +
- "FROM " + TAB_LOG + " " +
- "WHERE " +
- COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
- " AND " + COL_EVENT_TIME + " > %d " +
- " GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
- private static final String UNDECORATED_QUERY = "SELECT " +
- COL_PKG + ", " +
- "MAX(" + COL_EVENT_TIME + ") as max_time " +
- "FROM " + TAB_LOG + " " +
- "WHERE " + COL_UNDECORATED + "> 0 " +
- " AND " + COL_EVENT_TIME + " > %d " +
- "GROUP BY " + COL_PKG;
-
- public SQLiteLog(Context context) {
- HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- backgroundThread.start();
- mWriteHandler = new Handler(backgroundThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- NotificationRecord r = (NotificationRecord) msg.obj;
- long nowMs = System.currentTimeMillis();
- switch (msg.what) {
- case MSG_POST:
- writeEvent(r.getSbn().getPostTime(), EVENT_TYPE_POST, r);
- break;
- case MSG_CLICK:
- writeEvent(nowMs, EVENT_TYPE_CLICK, r);
- break;
- case MSG_REMOVE:
- writeEvent(nowMs, EVENT_TYPE_REMOVE, r);
- break;
- case MSG_DISMISS:
- writeEvent(nowMs, EVENT_TYPE_DISMISS, r);
- break;
- default:
- Log.wtf(TAG, "Unknown message type: " + msg.what);
- break;
- }
- }
- };
- mHelper = new SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TAB_LOG + " (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
- COL_EVENT_USER_ID + " INT," +
- COL_EVENT_TYPE + " INT," +
- COL_EVENT_TIME + " INT," +
- COL_KEY + " TEXT," +
- COL_PKG + " TEXT," +
- COL_NOTIFICATION_ID + " INT," +
- COL_TAG + " TEXT," +
- COL_WHEN_MS + " INT," +
- COL_DEFAULTS + " INT," +
- COL_FLAGS + " INT," +
- COL_IMPORTANCE_REQ + " INT," +
- COL_IMPORTANCE_FINAL + " INT," +
- COL_NOISY + " INT," +
- COL_MUTED + " INT," +
- COL_DEMOTED + " INT," +
- COL_CATEGORY + " TEXT," +
- COL_ACTION_COUNT + " INT," +
- COL_POSTTIME_MS + " INT," +
- COL_AIRTIME_MS + " INT," +
- COL_FIRST_EXPANSIONTIME_MS + " INT," +
- COL_AIRTIME_EXPANDED_MS + " INT," +
- COL_EXPAND_COUNT + " INT," +
- COL_UNDECORATED + " INT" +
- ")");
- }
-
- @Override
- public void onConfigure(SQLiteDatabase db) {
- // Memory optimization - close idle connections after 30s of inactivity
- setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- db.execSQL("DROP TABLE IF EXISTS " + TAB_LOG);
- onCreate(db);
- }
- }
- };
- }
-
- public void logPosted(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_POST, notification));
- }
-
- public void logClicked(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_CLICK, notification));
- }
-
- public void logRemoved(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_REMOVE, notification));
- }
-
- public void logDismissed(NotificationRecord notification) {
- mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_DISMISS, notification));
- }
-
- private JSONArray jsonPostFrequencies(DumpFilter filter) throws JSONException {
- JSONArray frequencies = new JSONArray();
- SQLiteDatabase db = mHelper.getReadableDatabase();
- long midnight = getMidnightMs();
- String q = String.format(STATS_QUERY, midnight, filter.since);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- int userId = cursor.getInt(0);
- String pkg = cursor.getString(1);
- if (filter != null && !filter.matches(pkg)) continue;
- int day = cursor.getInt(2);
- int count = cursor.getInt(3);
- int muted = cursor.getInt(4);
- int noisy = cursor.getInt(5);
- int demoted = cursor.getInt(6);
- JSONObject row = new JSONObject();
- row.put("user_id", userId);
- row.put("package", pkg);
- row.put("day", day);
- row.put("count", count);
- row.put("noisy", noisy);
- row.put("muted", muted);
- row.put("demoted", demoted);
- frequencies.put(row);
- }
- } finally {
- cursor.close();
- }
- return frequencies;
- }
-
- public void printPostFrequencies(PrintWriter pw, String indent, DumpFilter filter) {
- SQLiteDatabase db = mHelper.getReadableDatabase();
- long midnight = getMidnightMs();
- String q = String.format(STATS_QUERY, midnight, filter.since);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- int userId = cursor.getInt(0);
- String pkg = cursor.getString(1);
- if (filter != null && !filter.matches(pkg)) continue;
- int day = cursor.getInt(2);
- int count = cursor.getInt(3);
- int muted = cursor.getInt(4);
- int noisy = cursor.getInt(5);
- int demoted = cursor.getInt(6);
- pw.println(indent + "post_frequency{user_id=" + userId + ",pkg=" + pkg +
- ",day=" + day + ",count=" + count + ",muted=" + muted + "/" + noisy +
- ",demoted=" + demoted + "}");
- }
- } finally {
- cursor.close();
- }
- }
-
- private long getMidnightMs() {
- GregorianCalendar midnight = new GregorianCalendar();
- midnight.set(midnight.get(Calendar.YEAR), midnight.get(Calendar.MONTH),
- midnight.get(Calendar.DATE), 23, 59, 59);
- return midnight.getTimeInMillis();
- }
-
- private void writeEvent(long eventTimeMs, int eventType, NotificationRecord r) {
- ContentValues cv = new ContentValues();
- cv.put(COL_EVENT_USER_ID, r.getSbn().getUser().getIdentifier());
- cv.put(COL_EVENT_TIME, eventTimeMs);
- cv.put(COL_EVENT_TYPE, eventType);
- putNotificationIdentifiers(r, cv);
- if (eventType == EVENT_TYPE_POST) {
- putNotificationDetails(r, cv);
- } else {
- putPosttimeVisibility(r, cv);
- }
- cv.put(COL_UNDECORATED, (r.hasUndecoratedRemoteView() ? 1 : 0));
- SQLiteDatabase db = mHelper.getWritableDatabase();
- if (db.insert(TAB_LOG, null, cv) < 0) {
- Log.wtf(TAG, "Error while trying to insert values: " + cv);
- }
- sNumWrites++;
- pruneIfNecessary(db);
- }
-
- private void pruneIfNecessary(SQLiteDatabase db) {
- // Prune if we haven't in a while.
- long nowMs = System.currentTimeMillis();
- if (sNumWrites > PRUNE_MIN_WRITES ||
- nowMs - sLastPruneMs > PRUNE_MIN_DELAY_MS) {
- sNumWrites = 0;
- sLastPruneMs = nowMs;
- long horizonStartMs = nowMs - HORIZON_MS;
- try {
- int deletedRows = db.delete(TAB_LOG, COL_EVENT_TIME + " < ?",
- new String[]{String.valueOf(horizonStartMs)});
- Log.d(TAG, "Pruned event entries: " + deletedRows);
- } catch (SQLiteFullException e) {
- Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
- }
- }
- }
-
- private static void putNotificationIdentifiers(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_KEY, r.getSbn().getKey());
- outCv.put(COL_PKG, r.getSbn().getPackageName());
- }
-
- private static void putNotificationDetails(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_NOTIFICATION_ID, r.getSbn().getId());
- if (r.getSbn().getTag() != null) {
- outCv.put(COL_TAG, r.getSbn().getTag());
- }
- outCv.put(COL_WHEN_MS, r.getSbn().getPostTime());
- outCv.put(COL_FLAGS, r.getNotification().flags);
- final int before = r.stats.requestedImportance;
- final int after = r.getImportance();
- final boolean noisy = r.stats.isNoisy;
- outCv.put(COL_IMPORTANCE_REQ, before);
- outCv.put(COL_IMPORTANCE_FINAL, after);
- outCv.put(COL_DEMOTED, after < before ? 1 : 0);
- outCv.put(COL_NOISY, noisy);
- if (noisy && after < IMPORTANCE_HIGH) {
- outCv.put(COL_MUTED, 1);
- } else {
- outCv.put(COL_MUTED, 0);
- }
- if (r.getNotification().category != null) {
- outCv.put(COL_CATEGORY, r.getNotification().category);
- }
- outCv.put(COL_ACTION_COUNT, r.getNotification().actions != null ?
- r.getNotification().actions.length : 0);
- }
-
- private static void putPosttimeVisibility(NotificationRecord r, ContentValues outCv) {
- outCv.put(COL_POSTTIME_MS, r.stats.getCurrentPosttimeMs());
- outCv.put(COL_AIRTIME_MS, r.stats.getCurrentAirtimeMs());
- outCv.put(COL_EXPAND_COUNT, r.stats.userExpansionCount);
- outCv.put(COL_AIRTIME_EXPANDED_MS, r.stats.getCurrentAirtimeExpandedMs());
- outCv.put(COL_FIRST_EXPANSIONTIME_MS, r.stats.posttimeToFirstVisibleExpansionMs);
- }
-
- public void dump(PrintWriter pw, String indent, DumpFilter filter) {
- printPostFrequencies(pw, indent, filter);
- }
-
- public JSONObject dumpJson(DumpFilter filter) {
- JSONObject dump = new JSONObject();
- try {
- dump.put("post_frequency", jsonPostFrequencies(filter));
- dump.put("since", filter.since);
- dump.put("now", System.currentTimeMillis());
- } catch (JSONException e) {
- // pass
- }
- return dump;
- }
-
- public PulledStats remoteViewAggStats(long startMs) {
- PulledStats stats = new PulledStats(startMs);
- SQLiteDatabase db = mHelper.getReadableDatabase();
- String q = String.format(UNDECORATED_QUERY, startMs);
- Cursor cursor = db.rawQuery(q, null);
- try {
- for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
- String pkg = cursor.getString(0);
- long maxTimeMs = cursor.getLong(1);
- stats.addUndecoratedPackage(pkg, maxTimeMs);
- }
- } finally {
- cursor.close();
- }
- return stats;
- }
- }
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index c3cb42f95cc6..fd4a3024179c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -51,6 +51,7 @@ import android.service.notification.RankingHelperProto;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -1348,36 +1349,39 @@ public class PreferencesHelper implements RankingConfig {
return groups;
}
- public ArrayList<ConversationChannelWrapper> getConversations(boolean onlyImportant) {
+ public ArrayList<ConversationChannelWrapper> getConversations(IntArray userIds,
+ boolean onlyImportant) {
synchronized (mPackagePreferences) {
ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>();
-
for (PackagePreferences p : mPackagePreferences.values()) {
- int N = p.channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel nc = p.channels.valueAt(i);
- if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()
- && !nc.isDemoted()
- && (nc.isImportantConversation() || !onlyImportant)) {
- ConversationChannelWrapper conversation = new ConversationChannelWrapper();
- conversation.setPkg(p.pkg);
- conversation.setUid(p.uid);
- conversation.setNotificationChannel(nc);
- conversation.setParentChannelLabel(
- p.channels.get(nc.getParentChannelId()).getName());
- boolean blockedByGroup = false;
- if (nc.getGroup() != null) {
- NotificationChannelGroup group = p.groups.get(nc.getGroup());
- if (group != null) {
- if (group.isBlocked()) {
- blockedByGroup = true;
- } else {
- conversation.setGroupLabel(group.getName());
+ if (userIds.binarySearch(UserHandle.getUserId(p.uid)) >= 0) {
+ int N = p.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = p.channels.valueAt(i);
+ if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()
+ && !nc.isDemoted()
+ && (nc.isImportantConversation() || !onlyImportant)) {
+ ConversationChannelWrapper conversation =
+ new ConversationChannelWrapper();
+ conversation.setPkg(p.pkg);
+ conversation.setUid(p.uid);
+ conversation.setNotificationChannel(nc);
+ conversation.setParentChannelLabel(
+ p.channels.get(nc.getParentChannelId()).getName());
+ boolean blockedByGroup = false;
+ if (nc.getGroup() != null) {
+ NotificationChannelGroup group = p.groups.get(nc.getGroup());
+ if (group != null) {
+ if (group.isBlocked()) {
+ blockedByGroup = true;
+ } else {
+ conversation.setGroupLabel(group.getName());
+ }
}
}
- }
- if (!blockedByGroup) {
- conversations.add(conversation);
+ if (!blockedByGroup) {
+ conversations.add(conversation);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 330f99523507..f8115d39b375 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -299,6 +299,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
final ArraySet<File> unclaimedStages = newArraySet(
stagingDir.listFiles(sStageFilter));
+ // We also need to clean up orphaned staging directory for staged sessions
+ final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
+ unclaimedStages.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
+
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
@@ -393,6 +397,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
Slog.w(TAG, "Abandoning old session created at "
+ session.createdMillis);
valid = false;
+ } else if (isExtraSessionForStagedInstall(session)) {
+ valid = false;
} else {
valid = true;
}
@@ -423,6 +429,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
+ // Extra sessions are created during staged install on temporary basis. They should not be
+ // allowed to live across system server restart.
+ private boolean isExtraSessionForStagedInstall(PackageInstallerSession session) {
+ return (session.params.installFlags & PackageManager.INSTALL_DRY_RUN) != 0
+ || (session.params.installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
+ }
+
@GuardedBy("mSessions")
private void addHistoricalSessionLocked(PackageInstallerSession session) {
CharArrayWriter writer = new CharArrayWriter();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 33193dfda69e..d690ae9e70f1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1597,6 +1597,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
destroyInternal();
// Dispatch message to remove session from PackageInstallerService.
dispatchSessionFinished(error, detailMessage, null);
+ // TODO(b/173194203): clean up staged session in destroyInternal() call instead
+ if (isStaged() && stageDir != null) {
+ cleanStageDir();
+ }
}
private void onStorageUnhealthy() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0a2abff4cc5b..973d06f7ab81 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -331,6 +331,7 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -12450,12 +12451,17 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManager.addAllPermissionGroups(pkg, chatty);
}
+ // If a permission has had its defining app changed, or it has had its protection
+ // upgraded, we need to revoke apps that hold it
+ final List<String> permissionsWithChangedDefinition;
// Don't allow ephemeral applications to define new permissions.
if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
+ permissionsWithChangedDefinition = null;
Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
+ " ignored: instant apps cannot define new permissions.");
} else {
- mPermissionManager.addAllPermissions(pkg, chatty);
+ permissionsWithChangedDefinition =
+ mPermissionManager.addAllPermissions(pkg, chatty);
}
int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
@@ -12484,7 +12490,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- if (oldPkg != null) {
+ boolean hasOldPkg = oldPkg != null;
+ boolean hasPermissionDefinitionChanges =
+ !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
+ if (hasOldPkg || hasPermissionDefinitionChanges) {
// We need to call revokeRuntimePermissionsIfGroupChanged async as permission
// revoke callbacks from this method might need to kill apps which need the
// mPackages lock on a different thread. This would dead lock.
@@ -12495,9 +12504,16 @@ public class PackageManagerService extends IPackageManager.Stub
// won't be granted yet, hence new packages are no problem.
final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
- AsyncTask.execute(() ->
+ AsyncTask.execute(() -> {
+ if (hasOldPkg) {
mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
- allPackageNames));
+ allPackageNames);
+ }
+ if (hasPermissionDefinitionChanges) {
+ mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ permissionsWithChangedDefinition, allPackageNames);
+ }
+ });
}
}
@@ -18171,6 +18187,19 @@ public class PackageManagerService extends IPackageManager.Stub
final String packageName = versionedPackage.getPackageName();
final long versionCode = versionedPackage.getLongVersionCode();
final String internalPackageName;
+
+ try {
+ if (LocalServices.getService(ActivityTaskManagerInternal.class)
+ .isBaseOfLockedTask(packageName)) {
+ observer.onPackageDeleted(
+ packageName, PackageManager.DELETE_FAILED_APP_PINNED, null);
+ EventLog.writeEvent(0x534e4554, "127605586", -1, "");
+ return;
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
synchronized (mLock) {
// Normalize package name to handle renamed packages and static libs
internalPackageName = resolveInternalPackageNameLPr(packageName, versionCode);
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index ca506410e515..06b54b5c21fc 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -569,7 +569,8 @@ public class StagingManager {
}
}
- private void resumeSession(@NonNull PackageInstallerSession session) {
+ private void resumeSession(@NonNull PackageInstallerSession session)
+ throws PackageManagerException {
Slog.d(TAG, "Resuming session " + session.sessionId);
final boolean hasApex = sessionContainsApex(session);
@@ -634,10 +635,8 @@ public class StagingManager {
if (apexSessionInfo == null) {
final String errorMsg = "apexd did not know anything about a staged session "
+ "supposed to be activated";
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
if (isApexSessionFailed(apexSessionInfo)) {
String errorMsg = "APEX activation failed. Check logcat messages from apexd "
@@ -646,10 +645,8 @@ public class StagingManager {
errorMsg = "Session reverted due to crashing native process: "
+ mNativeFailureReason;
}
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) {
// Apexd did not apply the session for some unknown reason. There is no
@@ -657,42 +654,20 @@ public class StagingManager {
// it as failed.
final String errorMsg = "Staged session " + session.sessionId + "at boot "
+ "didn't activate nor fail. Marking it as failed anyway.";
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
}
// Handle apk and apk-in-apex installation
- try {
- if (hasApex) {
- checkInstallationOfApkInApexSuccessful(session);
- snapshotAndRestoreForApexSession(session);
- Slog.i(TAG, "APEX packages in session " + session.sessionId
- + " were successfully activated. Proceeding with APK packages, if any");
- }
- // The APEX part of the session is activated, proceed with the installation of APKs.
- Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
- installApksInSession(session);
- } catch (PackageManagerException e) {
- session.setStagedSessionFailed(e.error, e.getMessage());
- abortCheckpoint(session.sessionId, e.getMessage());
-
- // If checkpoint is not supported, we have to handle failure for one staged session.
- if (!hasApex) {
- return;
- }
-
- if (!mApexManager.revertActiveSessions()) {
- Slog.e(TAG, "Failed to abort APEXd session");
- } else {
- Slog.e(TAG,
- "Successfully aborted apexd session. Rebooting device in order to revert "
- + "to the previous state of APEXd.");
- mPowerManager.reboot(null);
- }
- return;
+ if (hasApex) {
+ checkInstallationOfApkInApexSuccessful(session);
+ snapshotAndRestoreForApexSession(session);
+ Slog.i(TAG, "APEX packages in session " + session.sessionId
+ + " were successfully activated. Proceeding with APK packages, if any");
}
+ // The APEX part of the session is activated, proceed with the installation of APKs.
+ Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
+ installApksInSession(session);
Slog.d(TAG, "Marking session " + session.sessionId + " as applied");
session.setStagedSessionApplied();
@@ -738,6 +713,25 @@ public class StagingManager {
return ret;
}
+ void onInstallationFailure(PackageInstallerSession session, PackageManagerException e) {
+ session.setStagedSessionFailed(e.error, e.getMessage());
+ abortCheckpoint(session.sessionId, e.getMessage());
+
+ // If checkpoint is not supported, we have to handle failure for one staged session.
+ if (!sessionContainsApex(session)) {
+ return;
+ }
+
+ if (!mApexManager.revertActiveSessions()) {
+ Slog.e(TAG, "Failed to abort APEXd session");
+ } else {
+ Slog.e(TAG,
+ "Successfully aborted apexd session. Rebooting device in order to revert "
+ + "to the previous state of APEXd.");
+ mPowerManager.reboot(null);
+ }
+ }
+
@NonNull
private PackageInstallerSession createAndWriteApkSession(
@NonNull PackageInstallerSession originalSession, boolean preReboot)
@@ -1088,6 +1082,26 @@ public class StagingManager {
return true;
}
+ /**
+ * Ensure that there is no active apex session staged in apexd for the given session.
+ *
+ * @return returns true if it is ensured that there is no active apex session, otherwise false
+ */
+ private boolean ensureActiveApexSessionIsAborted(PackageInstallerSession session) {
+ if (!sessionContainsApex(session)) {
+ return true;
+ }
+ final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId);
+ if (apexSession == null || isApexSessionFinalized(apexSession)) {
+ return true;
+ }
+ try {
+ return mApexManager.abortStagedSession(session.sessionId);
+ } catch (PackageManagerException ignore) {
+ return false;
+ }
+ }
+
private boolean isApexSessionFinalized(ApexSessionInfo session) {
/* checking if the session is in a final state, i.e., not active anymore */
return session.isUnknown || session.isActivationFailed || session.isSuccess
@@ -1181,7 +1195,16 @@ public class StagingManager {
} else {
// Session had already being marked ready. Start the checks to verify if there is any
// follow-up work.
- resumeSession(session);
+ try {
+ resumeSession(session);
+ } catch (PackageManagerException e) {
+ onInstallationFailure(session, e);
+ } catch (Exception e) {
+ Slog.e(TAG, "Staged install failed due to unhandled exception", e);
+ onInstallationFailure(session, new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ "Staged install failed due to unhandled exception: " + e));
+ }
}
}
@@ -1319,19 +1342,26 @@ public class StagingManager {
onPreRebootVerificationComplete(sessionId);
return;
}
- switch (msg.what) {
- case MSG_PRE_REBOOT_VERIFICATION_START:
- handlePreRebootVerification_Start(session);
- break;
- case MSG_PRE_REBOOT_VERIFICATION_APEX:
- handlePreRebootVerification_Apex(session);
- break;
- case MSG_PRE_REBOOT_VERIFICATION_APK:
- handlePreRebootVerification_Apk(session);
- break;
- case MSG_PRE_REBOOT_VERIFICATION_END:
- handlePreRebootVerification_End(session);
- break;
+ try {
+ switch (msg.what) {
+ case MSG_PRE_REBOOT_VERIFICATION_START:
+ handlePreRebootVerification_Start(session);
+ break;
+ case MSG_PRE_REBOOT_VERIFICATION_APEX:
+ handlePreRebootVerification_Apex(session);
+ break;
+ case MSG_PRE_REBOOT_VERIFICATION_APK:
+ handlePreRebootVerification_Apk(session);
+ break;
+ case MSG_PRE_REBOOT_VERIFICATION_END:
+ handlePreRebootVerification_End(session);
+ break;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Pre-reboot verification failed due to unhandled exception", e);
+ onPreRebootVerificationFailure(session,
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ "Pre-reboot verification failed due to unhandled exception: " + e);
}
}
@@ -1368,6 +1398,17 @@ public class StagingManager {
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget();
}
+ private void onPreRebootVerificationFailure(PackageInstallerSession session,
+ @SessionInfo.StagedSessionErrorCode int errorCode, String errorMessage) {
+ if (!ensureActiveApexSessionIsAborted(session)) {
+ Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+ // Safe to ignore active apex session abortion failure since session will be marked
+ // failed on next step and staging directory for session will be deleted.
+ }
+ session.setStagedSessionFailed(errorCode, errorMessage);
+ onPreRebootVerificationComplete(session.sessionId);
+ }
+
// Things to do when pre-reboot verification completes for a particular sessionId
private void onPreRebootVerificationComplete(int sessionId) {
// Remove it from mVerificationRunning so that verification is considered complete
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index a7f30fde703b..328b02a553b1 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -727,10 +727,14 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
"compiled_trace.pb");
try {
boolean exists = Files.exists(tracePath);
- Log.d(TAG, tracePath.toString() + (exists? " exists" : " doesn't exist"));
+ if (DEBUG) {
+ Log.d(TAG, tracePath.toString() + (exists? " exists" : " doesn't exist"));
+ }
if (exists) {
long bytes = Files.size(tracePath);
- Log.d(TAG, tracePath.toString() + " size is " + Long.toString(bytes));
+ if (DEBUG) {
+ Log.d(TAG, tracePath.toString() + " size is " + Long.toString(bytes));
+ }
return bytes > 0L;
}
return exists;
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index cfa0449aaf33..5e04171a3bca 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -83,6 +83,8 @@ public final class BasePermission {
final @PermissionType int type;
+ private boolean mPermissionDefinitionChanged;
+
String sourcePackageName;
int protectionLevel;
@@ -126,6 +128,11 @@ public final class BasePermission {
public String getSourcePackageName() {
return sourcePackageName;
}
+
+ public boolean isPermissionDefinitionChanged() {
+ return mPermissionDefinitionChanged;
+ }
+
public int getType() {
return type;
}
@@ -140,6 +147,10 @@ public final class BasePermission {
this.perm = perm;
}
+ public void setPermissionDefinitionChanged(boolean shouldOverride) {
+ mPermissionDefinitionChanged = shouldOverride;
+ }
+
public int[] computeGids(int userId) {
if (perUser) {
final int[] userGids = new int[gids.length];
@@ -322,6 +333,7 @@ public final class BasePermission {
final PackageSettingBase pkgSetting =
(PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName());
// Allow system apps to redefine non-system permissions
+ boolean ownerChanged = false;
if (bp != null && !Objects.equals(bp.sourcePackageName, p.getPackageName())) {
final boolean currentOwnerIsSystem;
if (bp.perm == null) {
@@ -347,6 +359,7 @@ public final class BasePermission {
String msg = "New decl " + pkg + " of permission "
+ p.getName() + " is system; overriding " + bp.sourcePackageName;
PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+ ownerChanged = true;
bp = null;
}
}
@@ -354,6 +367,7 @@ public final class BasePermission {
if (bp == null) {
bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL);
}
+ boolean wasNonRuntime = !bp.isRuntime();
StringBuilder r = null;
if (bp.perm == null) {
if (bp.sourcePackageName == null
@@ -397,6 +411,11 @@ public final class BasePermission {
&& Objects.equals(bp.perm.getName(), p.getName())) {
bp.protectionLevel = p.getProtectionLevel();
}
+ if (bp.isRuntime() && (ownerChanged || wasNonRuntime)) {
+ // If this is a runtime permission and the owner has changed, or this was a normal
+ // permission, then permission state should be cleaned up
+ bp.mPermissionDefinitionChanged = true;
+ }
if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
Log.d(TAG, " Permissions: " + r);
}
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 66d8b5974261..3ffca028b1c0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2344,8 +2344,74 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void addAllPermissions(AndroidPackage pkg, boolean chatty) {
+ /**
+ * If permissions are upgraded to runtime, or their owner changes to the system, then any
+ * granted permissions must be revoked.
+ *
+ * @param permissionsToRevoke A list of permission names to revoke
+ * @param allPackageNames All package names
+ * @param permissionCallback Callback for permission changed
+ */
+ private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ @NonNull List<String> permissionsToRevoke,
+ @NonNull ArrayList<String> allPackageNames,
+ @NonNull PermissionCallback permissionCallback) {
+
+ final int[] userIds = mUserManagerInt.getUserIds();
+ final int numPermissions = permissionsToRevoke.size();
+ final int numUserIds = userIds.length;
+ final int numPackages = allPackageNames.size();
+ final int callingUid = Binder.getCallingUid();
+
+ for (int permNum = 0; permNum < numPermissions; permNum++) {
+ String permName = permissionsToRevoke.get(permNum);
+ BasePermission bp = mSettings.getPermission(permName);
+ if (bp == null || !bp.isRuntime()) {
+ continue;
+ }
+ for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
+ final int userId = userIds[userIdNum];
+ for (int packageNum = 0; packageNum < numPackages; packageNum++) {
+ final String packageName = allPackageNames.get(packageNum);
+ final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
+ if (uid < Process.FIRST_APPLICATION_UID) {
+ // do not revoke from system apps
+ continue;
+ }
+ final int permissionState = checkPermissionImpl(permName, packageName,
+ userId);
+ final int flags = getPermissionFlags(permName, packageName, userId);
+ final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED
+ | FLAG_PERMISSION_POLICY_FIXED
+ | FLAG_PERMISSION_GRANTED_BY_DEFAULT
+ | FLAG_PERMISSION_GRANTED_BY_ROLE;
+ if (permissionState == PackageManager.PERMISSION_GRANTED
+ && (flags & flagMask) == 0) {
+ EventLog.writeEvent(0x534e4554, "154505240", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ EventLog.writeEvent(0x534e4554, "168319670", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ Slog.e(TAG, "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ try {
+ revokeRuntimePermissionInternal(permName, packageName,
+ false, callingUid, userId, null, permissionCallback);
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not revoke " + permName + " from "
+ + packageName, e);
+ }
+ }
+ }
+ }
+ bp.setPermissionDefinitionChanged(false);
+ }
+ }
+
+ private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
final int N = ArrayUtils.size(pkg.getPermissions());
+ ArrayList<String> definitionChangedPermissions = new ArrayList<>();
for (int i=0; i<N; i++) {
ParsedPermission p = pkg.getPermissions().get(i);
@@ -2367,21 +2433,26 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
+ final BasePermission bp;
if (p.isTree()) {
- final BasePermission bp = BasePermission.createOrUpdate(
+ bp = BasePermission.createOrUpdate(
mPackageManagerInt,
mSettings.getPermissionTreeLocked(p.getName()), p, pkg,
mSettings.getAllPermissionTreesLocked(), chatty);
mSettings.putPermissionTreeLocked(p.getName(), bp);
} else {
- final BasePermission bp = BasePermission.createOrUpdate(
+ bp = BasePermission.createOrUpdate(
mPackageManagerInt,
mSettings.getPermissionLocked(p.getName()),
p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
mSettings.putPermissionLocked(p.getName(), bp);
}
+ if (bp.isPermissionDefinitionChanged()) {
+ definitionChangedPermissions.add(p.getName());
+ }
}
}
+ return definitionChangedPermissions;
}
private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
@@ -4672,9 +4743,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
oldPackage, allPackageNames, mDefaultPermissionCallback);
}
+
+ @Override
+ public void revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ @NonNull List<String> permissionsToRevoke,
+ @NonNull ArrayList<String> allPackageNames) {
+ PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ permissionsToRevoke, allPackageNames, mDefaultPermissionCallback);
+ }
+
@Override
- public void addAllPermissions(AndroidPackage pkg, boolean chatty) {
- PermissionManagerService.this.addAllPermissions(pkg, chatty);
+ public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
+ return PermissionManagerService.this.addAllPermissions(pkg, chatty);
}
@Override
public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 37f40595450d..393e8527a991 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -254,12 +254,26 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@NonNull ArrayList<String> allPackageNames);
/**
+ * Some permissions might have been owned by a non-system package, and the system then defined
+ * said permission. Some other permissions may one have been install permissions, but are now
+ * runtime or higher. These permissions should be revoked.
+ *
+ * @param permissionsToRevoke A list of permission names to revoke
+ * @param allPackageNames All packages
+ */
+ public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged(
+ @NonNull List<String> permissionsToRevoke,
+ @NonNull ArrayList<String> allPackageNames);
+
+ /**
* Add all permissions in the given package.
* <p>
* NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
* the permission settings.
+ *
+ * @return A list of BasePermissions that were updated, and need to be revoked from packages
*/
- public abstract void addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
+ public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty);
public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3c42e930389b..c15cbb49d695 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1466,10 +1466,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
if (mHasFeatureLeanback) {
isSetupComplete &= isTvUserSetupComplete();
+ } else if (mHasFeatureAuto) {
+ isSetupComplete &= isAutoUserSetupComplete();
}
return isSetupComplete;
}
+ private boolean isAutoUserSetupComplete() {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ "android.car.SETUP_WIZARD_IN_PROGRESS", 0, UserHandle.USER_CURRENT) == 0;
+ }
+
private boolean isTvUserSetupComplete() {
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
@@ -2410,6 +2417,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
view = win.getDecorView();
+ // Ignore to show splash screen if the decorView is not opaque.
+ if (!view.isOpaque()) {
+ if (DEBUG_SPLASH_SCREEN) {
+ Slog.d(TAG, "addSplashScreen: the view of " + packageName
+ + " is not opaque, cancel it");
+ }
+ return null;
+ }
+
if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
+ packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index cc369356c1c9..9026262db897 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -127,9 +127,11 @@ public abstract class SoftRestrictedPermissionPolicy {
final boolean isWhiteListed;
boolean shouldApplyRestriction;
final int targetSDK;
+ final boolean hasLegacyExternalStorage;
final boolean hasRequestedLegacyExternalStorage;
- final boolean shouldPreserveLegacyExternalStorage;
+ final boolean hasRequestedPreserveLegacyExternalStorage;
final boolean hasWriteMediaStorageGrantedForUid;
+ final boolean isForcedScopedStorage;
if (appInfo != null) {
PackageManager pm = context.getPackageManager();
@@ -137,27 +139,27 @@ public abstract class SoftRestrictedPermissionPolicy {
LocalServices.getService(StorageManagerInternal.class);
int flags = pm.getPermissionFlags(permission, appInfo.packageName, user);
isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
+ hasLegacyExternalStorage = smInternal.hasLegacyExternalStorage(appInfo.uid);
hasRequestedLegacyExternalStorage = hasUidRequestedLegacyExternalStorage(
appInfo.uid, context);
hasWriteMediaStorageGrantedForUid = hasWriteMediaStorageGrantedForUid(
appInfo.uid, context);
- shouldPreserveLegacyExternalStorage = pkg.hasPreserveLegacyExternalStorage()
- && smInternal.hasLegacyExternalStorage(appInfo.uid);
+ hasRequestedPreserveLegacyExternalStorage =
+ pkg.hasPreserveLegacyExternalStorage();
targetSDK = getMinimumTargetSDK(context, appInfo, user);
- shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0
- || (targetSDK > Build.VERSION_CODES.Q
- && !shouldPreserveLegacyExternalStorage)
- // If the device is configured to force this app into scoped storage,
- // then we should apply the restriction
- || sForcedScopedStorageAppWhitelist.contains(appInfo.packageName);
+ shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+ isForcedScopedStorage = sForcedScopedStorageAppWhitelist
+ .contains(appInfo.packageName);
} else {
isWhiteListed = false;
shouldApplyRestriction = false;
targetSDK = 0;
+ hasLegacyExternalStorage = false;
hasRequestedLegacyExternalStorage = false;
- shouldPreserveLegacyExternalStorage = false;
+ hasRequestedPreserveLegacyExternalStorage = false;
hasWriteMediaStorageGrantedForUid = false;
+ isForcedScopedStorage = false;
}
// We have a check in PermissionPolicyService.PermissionToOpSynchroniser.setUidMode
@@ -175,14 +177,53 @@ public abstract class SoftRestrictedPermissionPolicy {
}
@Override
public boolean mayAllowExtraAppOp() {
- return !shouldApplyRestriction
- && (hasRequestedLegacyExternalStorage
- || hasWriteMediaStorageGrantedForUid
- || shouldPreserveLegacyExternalStorage);
+ // The only way to get LEGACY_STORAGE (if you didn't already have it)
+ // is that all of the following must be true:
+ // 1. The flag shouldn't be restricted
+ if (shouldApplyRestriction) {
+ return false;
+ }
+
+ // 2. The app shouldn't be in sForcedScopedStorageAppWhitelist
+ if (isForcedScopedStorage) {
+ return false;
+ }
+
+ // 3. The app has WRITE_MEDIA_STORAGE, OR
+ // the app already has legacy external storage or requested it,
+ // and is < R.
+ return hasWriteMediaStorageGrantedForUid
+ || ((hasLegacyExternalStorage || hasRequestedLegacyExternalStorage)
+ && targetSDK < Build.VERSION_CODES.R);
}
@Override
public boolean mayDenyExtraAppOpIfGranted() {
- return shouldApplyRestriction;
+ // If you're an app targeting < R, you can keep the app op for
+ // as long as you meet the conditions required to acquire it.
+ if (targetSDK < Build.VERSION_CODES.R) {
+ return !mayAllowExtraAppOp();
+ }
+
+ // For an app targeting R, the only way to lose LEGACY_STORAGE if you
+ // already had it is in one or more of the following conditions:
+ // 1. The flag became restricted
+ if (shouldApplyRestriction) {
+ return true;
+ }
+
+ // The package is now a part of the forced scoped storage whitelist
+ if (isForcedScopedStorage) {
+ return true;
+ }
+
+ // The package doesn't have WRITE_MEDIA_STORAGE,
+ // AND didn't request legacy storage to be preserved
+ if (!hasWriteMediaStorageGrantedForUid
+ && !hasRequestedPreserveLegacyExternalStorage) {
+ return true;
+ }
+
+ return false;
}
};
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1d949dc548da..061fabf3ab2a 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -5305,6 +5305,22 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public boolean isAmbientDisplaySuppressedForTokenByApp(@NonNull String token, int appUid) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_DREAM_STATE, null);
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_DREAM_SUPPRESSION, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isAmbientDisplayAvailable()
+ && mAmbientDisplaySuppressionController.isSuppressed(token, appUid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public boolean isAmbientDisplaySuppressed() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_DREAM_STATE, null);
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index aecf1f27da06..e09a45f9654b 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -77,8 +77,10 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.face.FaceManager;
+import android.hardware.face.FaceManager.GetFeatureCallback;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.health.V2_0.IHealth;
import android.net.ConnectivityManager;
@@ -247,6 +249,13 @@ public class StatsPullAtomService extends SystemService {
// 20% as a conservative estimate.
private static final int MAX_PROCSTATS_RAW_SHARD_SIZE = (int) (MAX_PROCSTATS_SHARD_SIZE * 1.20);
+ /**
+ * Threshold to filter out small CPU times at frequency per UID. Those small values appear
+ * because of more precise accounting in a BPF program. Discarding them reduces the data by at
+ * least 20% with negligible error.
+ */
+ private static final int MIN_CPU_TIME_PER_UID_FREQ = 10;
+
private final Object mThermalLock = new Object();
@GuardedBy("mThermalLock")
private IThermalService mThermalService;
@@ -1554,7 +1563,7 @@ public class StatsPullAtomService extends SystemService {
int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
- if (cpuFreqTimeMs[freqIndex] != 0) {
+ if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeInt(uid)
@@ -3327,18 +3336,39 @@ public class StatsPullAtomService extends SystemService {
try {
List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
int numUsers = users.size();
+ FaceManager faceManager = mContext.getSystemService(FaceManager.class);
+
for (int userNum = 0; userNum < numUsers; userNum++) {
int userId = users.get(userNum).getUserHandle().getIdentifier();
+ if (faceManager != null) {
+ // Store the current setting from the Face HAL, and upon next upload the value
+ // reported will be correct (given the user did not modify it).
+ faceManager.getFeature(userId, BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
+ new GetFeatureCallback() {
+ @Override
+ public void onCompleted(boolean success, int feature,
+ boolean value) {
+ if (feature == FaceManager.FEATURE_REQUIRE_ATTENTION
+ && success) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ value ? 1 : 0, userId);
+ }
+ }
+ }
+ );
+ }
+
int unlockKeyguardEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, 1, userId);
int unlockDismissesKeyguard = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 0, userId);
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 1, userId);
int unlockAttentionRequired = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, 1, userId);
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, 0, userId);
int unlockAppEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_APP_ENABLED, 1, userId);
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 61325cc78e74..0d11bef798ba 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -51,11 +51,15 @@ import android.app.AppGlobals;
import android.app.GrantedUriPermission;
import android.app.IUriGrantsManager;
import android.content.ClipData;
+import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.PathPermission;
@@ -115,13 +119,19 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
private static final String TAG = "UriGrantsManagerService";
// Maximum number of persisted Uri grants a package is allowed
private static final int MAX_PERSISTED_URI_GRANTS = 512;
- private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false;
+ private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
+ private static final String MEDIA_PROVIDER_MODULE_NAME = "com.android.mediaprovider";
+ private static final long MIN_DYNAMIC_PERMISSIONS_MP_VERSION = 301400000L;
private final Object mLock = new Object();
+ private final Context mContext;
private final H mH;
ActivityManagerInternal mAmInternal;
PackageManagerInternal mPmInternal;
+ private boolean isDynamicPermissionEnabledInMP = false;
+ private boolean isMPVersionChecked = false;
+
/** File storing persisted {@link #mGrantedUriPermissions}. */
@GuardedBy("mLock")
private final AtomicFile mGrantFile;
@@ -148,18 +158,19 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
private final SparseArray<ArrayMap<GrantUri, UriPermission>>
mGrantedUriPermissions = new SparseArray<>();
- private UriGrantsManagerService() {
- this(SystemServiceManager.ensureSystemDir());
+ private UriGrantsManagerService(Context context) {
+ this(context, SystemServiceManager.ensureSystemDir());
}
- private UriGrantsManagerService(File systemDir) {
+ private UriGrantsManagerService(Context context, File systemDir) {
+ mContext = context;
mH = new H(IoThread.get().getLooper());
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
}
@VisibleForTesting
- static UriGrantsManagerService createForTest(File systemDir) {
- final UriGrantsManagerService service = new UriGrantsManagerService(systemDir);
+ static UriGrantsManagerService createForTest(Context context, File systemDir) {
+ final UriGrantsManagerService service = new UriGrantsManagerService(context, systemDir);
service.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
service.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
return service;
@@ -179,7 +190,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
public Lifecycle(Context context) {
super(context);
- mService = new UriGrantsManagerService();
+ mService = new UriGrantsManagerService(context);
}
@Override
@@ -991,7 +1002,9 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
// If this provider says that grants are always required, we need to
// consult it directly to determine if the UID has permission
final boolean forceMet;
- if (ENABLE_DYNAMIC_PERMISSIONS && pi.forceUriPermissions) {
+ if (ENABLE_DYNAMIC_PERMISSIONS
+ && pi.forceUriPermissions
+ && isDynamicPermissionEnabledInMP()) {
final int providerUserId = UserHandle.getUserId(pi.applicationInfo.uid);
final int clientUserId = UserHandle.getUserId(uid);
if (providerUserId == clientUserId) {
@@ -1009,6 +1022,35 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
return readMet && writeMet && forceMet;
}
+ /**
+ * Returns true if the available MediaProvider version contains the changes that enable dynamic
+ * permission.
+ */
+ private boolean isDynamicPermissionEnabledInMP() {
+ if (isMPVersionChecked) {
+ return isDynamicPermissionEnabledInMP;
+ }
+
+ try {
+ ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo(
+ MEDIA_PROVIDER_MODULE_NAME, PackageManager.MODULE_APEX_NAME);
+ PackageInfo packageInfo =
+ mContext.getPackageManager().getPackageInfo(
+ moduleInfo.getPackageName(), PackageManager.MATCH_APEX);
+ isDynamicPermissionEnabledInMP =
+ packageInfo.getLongVersionCode() >= MIN_DYNAMIC_PERMISSIONS_MP_VERSION;
+ } catch (NameNotFoundException e) {
+ Slog.i(TAG, "Module name not found: " + MEDIA_PROVIDER_MODULE_NAME);
+ // If module is not found, then MP changes are expected to be there (because both this
+ // change and the module change will be mandated together for non-module builds).
+ isDynamicPermissionEnabledInMP = true;
+ } finally {
+ isMPVersionChecked = true;
+ }
+
+ return isDynamicPermissionEnabledInMP;
+ }
+
@GuardedBy("mLock")
private void removeUriPermissionIfNeededLocked(UriPermission perm) {
if (perm.modeFlags != 0) {
diff --git a/services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java b/services/core/java/com/android/server/utils/DeviceConfigInterface.java
index ab7e7f63cafd..ff609031b57c 100644
--- a/services/core/java/com/android/server/wm/utils/DeviceConfigInterface.java
+++ b/services/core/java/com/android/server/utils/DeviceConfigInterface.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.wm.utils;
+package com.android.server.utils;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -54,6 +54,11 @@ public interface DeviceConfigInterface {
boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
/**
+ * @see DeviceConfig#getFloat
+ */
+ float getFloat(@NonNull String namespace, @NonNull String name, float defaultValue);
+
+ /**
* @see DeviceConfig#addOnPropertiesChangedListener
*/
void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
@@ -96,6 +101,12 @@ public interface DeviceConfigInterface {
}
@Override
+ public float getFloat(@NonNull String namespace, @NonNull String name,
+ float defaultValue) {
+ return DeviceConfig.getFloat(namespace, name, defaultValue);
+ }
+
+ @Override
public void addOnPropertiesChangedListener(String namespace, Executor executor,
DeviceConfig.OnPropertiesChangedListener listener) {
DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index ca5e38df066e..b2c1f5ba862d 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -69,6 +69,7 @@ import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallba
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -92,6 +93,9 @@ final class AccessibilityController {
private SparseArray<WindowsForAccessibilityObserver> mWindowsForAccessibilityObserver =
new SparseArray<>();
+ // Set to true if initializing window population complete.
+ private boolean mAllObserversInitialized = true;
+
public boolean setMagnificationCallbacksLocked(int displayId,
MagnificationCallbacks callbacks) {
boolean result = false;
@@ -110,7 +114,7 @@ final class AccessibilityController {
}
} else {
final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
- if (displayMagnifier == null) {
+ if (displayMagnifier == null) {
throw new IllegalStateException("Magnification callbacks already cleared!");
}
displayMagnifier.destroyLocked();
@@ -150,8 +154,10 @@ final class AccessibilityController {
"Windows for accessibility callback of display "
+ displayId + " already set!");
}
- mWindowsForAccessibilityObserver.put(displayId,
- new WindowsForAccessibilityObserver(mService, displayId, callback));
+ final WindowsForAccessibilityObserver observer =
+ new WindowsForAccessibilityObserver(mService, displayId, callback);
+ mWindowsForAccessibilityObserver.put(displayId, observer);
+ mAllObserversInitialized &= observer.mInitialized;
} else {
if (isEmbeddedDisplay(dc)) {
// If this display is an embedded one, its window observer should be removed along
@@ -275,6 +281,41 @@ final class AccessibilityController {
if (observer != null) {
observer.performComputeChangedWindowsNotLocked(false);
}
+ // Since we abandon initializing observers if no window has focus, make sure all observers
+ // are initialized.
+ sendCallbackToUninitializedObserversIfNeeded();
+ }
+
+ private void sendCallbackToUninitializedObserversIfNeeded() {
+ List<WindowsForAccessibilityObserver> unInitializedObservers;
+ synchronized (mService.mGlobalLock) {
+ if (mAllObserversInitialized) {
+ return;
+ }
+ if (mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus == null) {
+ return;
+ }
+ unInitializedObservers = new ArrayList<>();
+ for (int i = mWindowsForAccessibilityObserver.size() - 1; i >= 0; --i) {
+ final WindowsForAccessibilityObserver observer =
+ mWindowsForAccessibilityObserver.valueAt(i);
+ if (!observer.mInitialized) {
+ unInitializedObservers.add(observer);
+ }
+ }
+ // Reset the flag to record the new added observer.
+ mAllObserversInitialized = true;
+ }
+
+ boolean areAllObserversInitialized = true;
+ for (int i = unInitializedObservers.size() - 1; i >= 0; --i) {
+ final WindowsForAccessibilityObserver observer = unInitializedObservers.get(i);
+ observer.performComputeChangedWindowsNotLocked(true);
+ areAllObserversInitialized &= observer.mInitialized;
+ }
+ synchronized (mService.mGlobalLock) {
+ mAllObserversInitialized &= areAllObserversInitialized;
+ }
}
/**
@@ -361,6 +402,8 @@ final class AccessibilityController {
+ "Magnification display# " + mDisplayMagnifiers.keyAt(i));
}
}
+ pw.println(prefix
+ + "mWindowsForAccessibilityObserver=" + mWindowsForAccessibilityObserver);
}
private void removeObserverOfEmbeddedDisplay(WindowsForAccessibilityObserver
@@ -1214,6 +1257,9 @@ final class AccessibilityController {
private final IntArray mEmbeddedDisplayIdList = new IntArray(0);
+ // Set to true if initializing window population complete.
+ private boolean mInitialized;
+
public WindowsForAccessibilityObserver(WindowManagerService windowManagerService,
int displayId,
WindowsForAccessibilityCallback callback) {
@@ -1272,10 +1318,17 @@ final class AccessibilityController {
// the window manager is still looking for where to put it.
// We will do the work when we get a focus change callback.
final WindowState topFocusedWindowState = getTopFocusWindow();
- if (topFocusedWindowState == null) return;
+ if (topFocusedWindowState == null) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "top focused window is null, compute it again later");
+ }
+ return;
+ }
final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
if (dc == null) {
+ //It should not happen because it is created while adding the callback.
+ Slog.w(LOG_TAG, "display content is null, should be created later");
return;
}
final Display display = dc.getDisplay();
@@ -1362,6 +1415,7 @@ final class AccessibilityController {
// Recycle the windows as we do not need them.
clearAndRecycleWindows(windows);
+ mInitialized = true;
}
private boolean windowMattersToAccessibility(WindowState windowState,
@@ -1547,6 +1601,16 @@ final class AccessibilityController {
return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
}
+ @Override
+ public String toString() {
+ return "WindowsForAccessibilityObserver{"
+ + "mDisplayId=" + mDisplayId
+ + ", mEmbeddedDisplayIdList="
+ + Arrays.toString(mEmbeddedDisplayIdList.toArray())
+ + ", mInitialized=" + mInitialized
+ + '}';
+ }
+
private class MyHandler extends Handler {
public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 7e6abf8b5029..8f59eef49516 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -129,7 +129,6 @@ class ActivityMetricsLogger {
*/
private static final int IGNORE_CALLER = -1;
private static final int INVALID_DELAY = -1;
- private static final int INVALID_TRANSITION_TYPE = -1;
// Preallocated strings we are sending to tron, so we don't have to allocate a new one every
// time we log.
@@ -224,22 +223,19 @@ class ActivityMetricsLogger {
static TransitionInfo create(@NonNull ActivityRecord r,
@NonNull LaunchingState launchingState, boolean processRunning,
boolean processSwitch, int startResult) {
- int transitionType = INVALID_TRANSITION_TYPE;
+ if (startResult != START_SUCCESS && startResult != START_TASK_TO_FRONT) {
+ return null;
+ }
+ final int transitionType;
if (processRunning) {
- if (startResult == START_SUCCESS) {
- transitionType = TYPE_TRANSITION_WARM_LAUNCH;
- } else if (startResult == START_TASK_TO_FRONT) {
- transitionType = TYPE_TRANSITION_HOT_LAUNCH;
- }
- } else if (startResult == START_SUCCESS || startResult == START_TASK_TO_FRONT) {
+ transitionType = r.attachedToProcess()
+ ? TYPE_TRANSITION_HOT_LAUNCH
+ : TYPE_TRANSITION_WARM_LAUNCH;
+ } else {
// Task may still exist when cold launching an activity and the start result will be
// set to START_TASK_TO_FRONT. Treat this as a COLD launch.
transitionType = TYPE_TRANSITION_COLD_LAUNCH;
}
- if (transitionType == INVALID_TRANSITION_TYPE) {
- // That means the startResult is neither START_SUCCESS nor START_TASK_TO_FRONT.
- return null;
- }
return new TransitionInfo(r, launchingState, transitionType, processRunning,
processSwitch);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index d4dd35f53cf0..eb749f6e06bb 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -568,4 +568,10 @@ public abstract class ActivityTaskManagerInternal {
/** Set all associated companion app that belongs to an userId. */
public abstract void setCompanionAppPackages(int userId, Set<String> companionAppPackages);
+
+ /**
+ * @param packageName The package to check
+ * @return Whether the package is the base of any locked task
+ */
+ public abstract boolean isBaseOfLockedTask(String packageName);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 0542ef9b09a4..8dbd661cff91 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -7473,5 +7473,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mCompanionAppUidsMap.put(userId, result);
}
}
+
+
+ @Override
+ public boolean isBaseOfLockedTask(String packageName) {
+ synchronized (mGlobalLock) {
+ return getLockTaskController().isBaseOfLockedTask(packageName);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 2be3acc52058..fa2a42e72054 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -200,6 +200,9 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
Comparator.comparingInt(WindowToken::getWindowLayerFromType);
private final Predicate<WindowState> mGetOrientingWindow = w -> {
+ if (!w.isVisible() || !w.mLegacyPolicyVisibilityAfterAnim) {
+ return false;
+ }
final WindowManagerPolicy policy = mWmService.mPolicy;
if (policy.isKeyguardHostWindow(w.mAttrs)) {
if (mWmService.mKeyguardGoingAway) {
@@ -235,6 +238,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
@Override
int getOrientation(int candidate) {
+ mLastOrientationSource = null;
// Find a window requesting orientation.
final WindowState win = getWindow(mGetOrientingWindow);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e36b84fb37c4..fa6baa1d9225 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -188,6 +188,8 @@ import android.view.IWindow;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputWindowHandle;
+import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationDefinition;
@@ -1666,6 +1668,28 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
+ void notifyInsetsChanged(Consumer<WindowState> dispatchInsetsChanged) {
+ if (mFixedRotationLaunchingApp != null) {
+ // The insets state of fixed rotation app is a rotated copy. Make sure the visibilities
+ // of insets sources are consistent with the latest state.
+ final InsetsState rotatedState =
+ mFixedRotationLaunchingApp.getFixedRotationTransformInsetsState();
+ if (rotatedState != null) {
+ final InsetsState state = mInsetsStateController.getRawInsetsState();
+ for (int i = 0; i < InsetsState.SIZE; i++) {
+ final InsetsSource source = state.peekSource(i);
+ if (source != null) {
+ rotatedState.setSourceVisible(i, source.isVisible());
+ }
+ }
+ }
+ }
+ forAllWindows(dispatchInsetsChanged, true /* traverseTopToBottom */);
+ if (mRemoteInsetsControlTarget != null) {
+ mRemoteInsetsControlTarget.notifyInsetsChanged();
+ }
+ }
+
/**
* Update rotation of the display.
*
@@ -5703,7 +5727,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return;
}
- if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp) {
+ if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp
+ && animatingRecents.isVisible()) {
// The recents activity should be going to be invisible (switch to another app or
// return to original top). Only clear the top launching record without finishing
// the transform immediately because it won't affect display orientation. And before
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 515d1f58d3ef..29881cc761b2 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -549,11 +549,10 @@ public class DisplayPolicy {
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
- final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
- || mNavigationBarPosition == NAV_BAR_RIGHT;
- if (mNavigationBar != null && sideAllowed
- && !mSystemGestures.currentGestureStartedInRegion(
- excludedRegion)) {
+ final boolean excluded =
+ mSystemGestures.currentGestureStartedInRegion(excludedRegion);
+ if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
+ || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
@@ -567,11 +566,10 @@ public class DisplayPolicy {
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
- final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
- || mNavigationBarPosition == NAV_BAR_LEFT;
- if (mNavigationBar != null && sideAllowed
- && !mSystemGestures.currentGestureStartedInRegion(
- excludedRegion)) {
+ final boolean excluded =
+ mSystemGestures.currentGestureStartedInRegion(excludedRegion);
+ if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
+ || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
@@ -3437,17 +3435,16 @@ public class DisplayPolicy {
}
final InsetsState requestedState = controlTarget.getRequestedInsetsState();
+ final InsetsSource nbSource = requestedState.peekSource(ITYPE_NAVIGATION_BAR);
+ final InsetsSource sbSource = requestedState.peekSource(ITYPE_STATUS_BAR);
+ final InsetsSource enbSource = requestedState.peekSource(ITYPE_EXTRA_NAVIGATION_BAR);
+ final InsetsSource cbSource = requestedState.peekSource(ITYPE_CLIMATE_BAR);
final @InsetsType int restorePositionTypes =
- (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ (nbSource != null && nbSource.isVisible() ? Type.navigationBars() : 0)
+ | (sbSource != null && sbSource.isVisible() ? Type.statusBars() : 0)
+ | (mExtraNavBarAlt != null && enbSource != null && enbSource.isVisible()
? Type.navigationBars() : 0)
- | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
- ? Type.statusBars() : 0)
- | (mExtraNavBarAlt != null
- && requestedState.getSourceOrDefaultVisibility(
- ITYPE_EXTRA_NAVIGATION_BAR)
- ? Type.navigationBars() : 0)
- | (mClimateBarAlt != null
- && requestedState.getSourceOrDefaultVisibility(ITYPE_CLIMATE_BAR)
+ | (mClimateBarAlt != null && cbSource != null && cbSource.isVisible()
? Type.statusBars() : 0);
if (swipeTarget == mNavigationBar
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index aac6b2544c4f..e925b054a92b 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -27,7 +27,7 @@ import android.util.ArraySet;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
-import com.android.server.wm.utils.DeviceConfigInterface;
+import com.android.server.utils.DeviceConfigInterface;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index fd67db1d5cc9..be1d0fc0ecc8 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -36,6 +36,7 @@ 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;
@@ -212,11 +213,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;
}
@@ -252,11 +263,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,
@@ -290,7 +304,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();
@@ -298,6 +312,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/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 68405c40ce37..c56457a0e5da 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -107,6 +107,10 @@ class InsetsStateController {
* @return The state stripped of the necessary information.
*/
InsetsState getInsetsForDispatch(@NonNull WindowState target) {
+ final InsetsState rotatedState = target.mToken.getFixedRotationTransformInsetsState();
+ if (rotatedState != null) {
+ return rotatedState;
+ }
final InsetsSourceProvider provider = target.getControllableInsetProvider();
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
@@ -473,10 +477,7 @@ class InsetsStateController {
}
void notifyInsetsChanged() {
- mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
- if (mDisplayContent.mRemoteInsetsControlTarget != null) {
- mDisplayContent.mRemoteInsetsControlTarget.notifyInsetsChanged();
- }
+ mDisplayContent.notifyInsetsChanged(mDispatchInsetsChanged);
}
void dump(String prefix, PrintWriter pw) {
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index c36dede013f4..c4a42ab7e7be 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -871,6 +871,21 @@ public class LockTaskController {
}
/**
+ * @param packageName The package to check
+ * @return Whether the package is the base of any locked task
+ */
+ boolean isBaseOfLockedTask(String packageName) {
+ for (int i = 0; i < mLockTaskModeTasks.size(); i++) {
+ final Intent bi = mLockTaskModeTasks.get(i).getBaseIntent();
+ if (bi != null && packageName.equals(bi.getComponent()
+ .getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Gets the cached value of LockTask feature flags for a specific user.
*/
private int getLockTaskFeaturesForUser(int userId) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0d55dece34a9..eaf76938e2e8 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -994,9 +994,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- // Remove all deferred displays stacks, tasks, and activities.
- handleCompleteDeferredRemoval();
-
forAllDisplays(dc -> {
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
dc.updateSystemGestureExclusion();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index e85049cad2f4..3c0cb17af603 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -480,9 +480,7 @@ 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.getFrameLw(), insetsState);
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 6cc0ba5e209c..94229b94eb64 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -245,11 +245,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 {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 9d0bac9dd290..9d07304aa2b9 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -143,6 +143,9 @@ public class WindowAnimator {
ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION animate");
mService.openSurfaceTransaction();
try {
+ // Remove all deferred displays, tasks, and activities.
+ mService.mRoot.handleCompleteDeferredRemoval();
+
final AccessibilityController accessibilityController =
mService.mAccessibilityController;
final int numDisplays = mDisplayContentsAnimators.size();
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 0ade5867d059..6cd6a57eedd4 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1060,7 +1060,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// descendant. E.g. if a display is pending to be removed because it contains an
// activity with {@link ActivityRecord#mIsExiting} is true, the display may be
// removed when completing the removal of the last activity from
- // {@link ActivityRecord#checkCompleteDeferredRemoval}.
+ // {@link ActivityRecord#handleCompleteDeferredRemoval}.
return false;
}
}
@@ -2555,8 +2555,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
pw.print(prefix); pw.println("ContainerAnimator:");
mSurfaceAnimator.dump(pw, prefix + " ");
}
- if (mLastOrientationSource != null) {
+ if (mLastOrientationSource != null && this == mDisplayContent) {
pw.println(prefix + "mLastOrientationSource=" + mLastOrientationSource);
+ pw.println(prefix + "deepestLastOrientationSource=" + getLastOrientationSource());
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index b0c5dbc6cca3..a5ebf9ac74b9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -23,7 +23,7 @@ import android.provider.AndroidDeviceConfig;
import android.provider.DeviceConfig;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.wm.utils.DeviceConfigInterface;
+import com.android.server.utils.DeviceConfigInterface;
import java.io.PrintWriter;
import java.util.Objects;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b7a2eb3c705d..d9594a40bde3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -282,8 +282,8 @@ import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
import com.android.server.power.ShutdownThread;
import com.android.server.protolog.ProtoLogImpl;
import com.android.server.protolog.common.ProtoLog;
+import com.android.server.utils.DeviceConfigInterface;
import com.android.server.utils.PriorityDump;
-import com.android.server.wm.utils.DeviceConfigInterface;
import java.io.BufferedWriter;
import java.io.DataInputStream;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f9b5e0e70588..2329a6082f33 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1526,11 +1526,11 @@ 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() {
- final InsetsState insetsState = mToken.getFixedRotationTransformInsetsState();
- if (insetsState != null) {
- return insetsState;
- }
return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index faf3f06a3035..bf10526aeec2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -641,6 +641,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean mIsWatch;
/**
+ * Whether or not this device is an automotive.
+ */
+ private final boolean mIsAutomotive;
+
+ /**
* Whether this device has the telephony feature.
*/
final boolean mHasTelephonyFeature;
@@ -2567,6 +2572,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.hasSystemFeature(PackageManager.FEATURE_WATCH);
mHasTelephonyFeature = mInjector.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+ mIsAutomotive = mInjector.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
mBackgroundHandler = BackgroundThread.getHandler();
// Needed when mHasFeature == false, because it controls the certificate warning text.
@@ -6080,9 +6087,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Require authentication for the device or profile
if (userToLock == UserHandle.USER_ALL) {
- // Power off the display
- mInjector.powerManagerGoToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
+ if (mIsAutomotive) {
+ if (VERBOSE_LOG) {
+ Slog.v(LOG_TAG, "lockNow(): not powering off display on automotive"
+ + " build");
+ }
+ } else {
+ // Power off the display
+ mInjector.powerManagerGoToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
+ }
mInjector.getIWindowManager().lockNow(null);
} else {
mInjector.getTrustManager().setDeviceLockedForUser(userToLock, true);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 979f4e179e95..e57097e48881 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -48,7 +48,6 @@ android_test {
// TODO: remove once Android migrates to JUnit 4.12,
// which provides assertThrows
"testng",
-
],
aidl: {
@@ -110,6 +109,7 @@ java_library {
"utils/**/*.java",
"utils/**/*.kt",
"utils-mockito/**/*.kt",
+ ":services.core-sources-deviceconfig-interface",
],
static_libs: [
"junit",
@@ -126,6 +126,7 @@ java_library {
"utils/**/*.java",
"utils/**/*.kt",
"utils-mockito/**/*.kt",
+ ":services.core-sources-deviceconfig-interface",
],
static_libs: [
"junit",
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 6db3233b0266..36cfcc6c2e83 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -77,6 +77,7 @@
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
<uses-permission android:name="android.permission.DUMP"/>
<uses-permission android:name="android.permission.READ_DREAM_STATE"/>
+ <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION"/>
<uses-permission android:name="android.permission.WRITE_DREAM_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java
index 538e2d51e88f..0e787853f617 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java
@@ -26,6 +26,7 @@ import android.accessibilityservice.AccessibilityService;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
+import android.os.Handler;
import android.view.MotionEvent;
import androidx.test.InstrumentationRegistry;
@@ -56,7 +57,8 @@ public class GestureManifoldTest {
// Construct a testable GestureManifold.
mResultListener = mock(GestureManifold.Listener.class);
mState = new TouchState();
- mManifold = new GestureManifold(context, mResultListener, mState);
+ Handler handler = new Handler(context.getMainLooper());
+ mManifold = new GestureManifold(context, mResultListener, mState, handler);
// Play the role of touch explorer in updating the shared state.
when(mResultListener.onGestureStarted()).thenReturn(onGestureStarted());
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 9053234aa220..13587bc70b24 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -16,6 +16,8 @@
package com.android.server.accessibility.gestures;
+import static android.view.ViewConfiguration.getDoubleTapTimeout;
+
import static com.android.server.accessibility.gestures.TouchState.STATE_CLEAR;
import static com.android.server.accessibility.gestures.TouchState.STATE_DELEGATING;
import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGING;
@@ -23,6 +25,7 @@ import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_E
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.content.Context;
@@ -31,6 +34,7 @@ import android.os.SystemClock;
import android.testing.DexmakerShareClassLoaderRule;
import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -52,6 +56,8 @@ import java.util.List;
public class TouchExplorerTest {
private static final String LOG_TAG = "TouchExplorerTest";
+ // The constant of mDetermineUserIntentTimeout.
+ private static final int USER_INTENT_TIMEOUT = getDoubleTapTimeout();
private static final int FLAG_1FINGER = 0x8000;
private static final int FLAG_2FINGERS = 0x0100;
private static final int FLAG_3FINGERS = 0x0200;
@@ -72,6 +78,8 @@ public class TouchExplorerTest {
private EventStreamTransformation mCaptor;
private MotionEvent mLastEvent;
private TouchExplorer mTouchExplorer;
+ private Context mContext;
+ private int mTouchSlop;
private long mLastDownTime = Integer.MIN_VALUE;
// mock package-private GestureManifold class
@@ -91,7 +99,9 @@ public class TouchExplorerTest {
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
mEvents.add(0, event.copy());
// LastEvent may not match if we're clearing the state
- if (mLastEvent != null) {
+ // The last event becomes ACTION_UP event when sending the ACTION_CANCEL event,
+ // so ignoring the ACTION_CANCEL event checking.
+ if (mLastEvent != null && rawEvent.getActionMasked() != MotionEvent.ACTION_CANCEL) {
MotionEventMatcher lastEventMatcher = new MotionEventMatcher(mLastEvent);
assertThat(rawEvent, lastEventMatcher);
}
@@ -109,14 +119,52 @@ public class TouchExplorerTest {
@Before
public void setUp() {
- Context context = InstrumentationRegistry.getContext();
- AccessibilityManagerService ams = new AccessibilityManagerService(context);
+ mContext = InstrumentationRegistry.getContext();
+ mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ AccessibilityManagerService ams = new AccessibilityManagerService(mContext);
GestureManifold detector = mock(GestureManifold.class);
mCaptor = new EventCaptor();
- mTouchExplorer = new TouchExplorer(context, ams, detector);
+ mTouchExplorer = new TouchExplorer(mContext, ams, detector);
mTouchExplorer.setNext(mCaptor);
}
+ /**
+ * Test the case where the event location is correct when clicking after the following
+ * situation happened: entering the delegate state through doubleTapAndHold gesture and
+ * receiving a cancel event to return the clear state.
+ */
+ @Test
+ public void testClick_afterCanceledDoubleTapAndHold_eventLocationIsCorrect()
+ throws InterruptedException {
+ // Generates the click position by this click operation, otherwise the offset used
+ // while delegating could not be set.
+ send(downEvent(DEFAULT_X + 10, DEFAULT_Y + 10));
+ // Waits for transition to touch exploring state.
+ Thread.sleep(2 * USER_INTENT_TIMEOUT);
+ send(upEvent());
+
+ // Simulates detecting the doubleTapAndHold gesture and enters the delegate state.
+ final MotionEvent sendEvent =
+ fromTouchscreen(downEvent(DEFAULT_X + 100, DEFAULT_Y + 100));
+ mTouchExplorer.onDoubleTapAndHold(sendEvent, sendEvent, 0);
+ assertState(STATE_DELEGATING);
+
+ send(cancelEvent());
+
+ // Generates the click operation, and checks the event location of the ACTION_HOVER_ENTER
+ // event is correct.
+ send(downEvent());
+ // Waits for transition to touch exploring state.
+ Thread.sleep(2 * USER_INTENT_TIMEOUT);
+ send(upEvent());
+
+ final List<MotionEvent> events = getCapturedEvents();
+ assertTrue(events.stream().anyMatch(
+ motionEvent -> motionEvent.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
+ && motionEvent.getX() == DEFAULT_X
+ && motionEvent.getY() == DEFAULT_Y));
+ }
+
@Test
public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() {
goFromStateClearTo(STATE_MOVING_2FINGERS);
@@ -158,7 +206,7 @@ public class TouchExplorerTest {
goFromStateClearTo(STATE_DRAGGING_2FINGERS);
assertState(STATE_DRAGGING);
- assertCapturedEvents(MotionEvent.ACTION_DOWN);
+ assertCapturedEvents(MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE);
assertCapturedEventsNoHistory();
}
@@ -170,6 +218,7 @@ public class TouchExplorerTest {
assertState(STATE_DELEGATING);
assertCapturedEvents(
/* goto dragging state */ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_MOVE,
/* leave dragging state */ MotionEvent.ACTION_UP,
MotionEvent.ACTION_DOWN,
MotionEvent.ACTION_POINTER_DOWN);
@@ -226,13 +275,13 @@ public class TouchExplorerTest {
break;
case STATE_DRAGGING_2FINGERS: {
goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER);
- moveEachPointers(mLastEvent, p(10, 0), p(10, 0));
+ moveEachPointers(mLastEvent, p(mTouchSlop, 0), p(mTouchSlop, 0));
send(mLastEvent);
}
break;
case STATE_PINCH_2FINGERS: {
goFromStateClearTo(STATE_DRAGGING_2FINGERS);
- moveEachPointers(mLastEvent, p(10, 0), p(-10, 1));
+ moveEachPointers(mLastEvent, p(mTouchSlop, 0), p(-mTouchSlop, 1));
send(mLastEvent);
}
break;
@@ -289,6 +338,19 @@ public class TouchExplorerTest {
return ((EventCaptor) mCaptor).mEvents;
}
+ private MotionEvent cancelEvent() {
+ mLastDownTime = SystemClock.uptimeMillis();
+ return fromTouchscreen(
+ MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_CANCEL,
+ DEFAULT_X, DEFAULT_Y, 0));
+ }
+
+ private MotionEvent downEvent(float x, float y) {
+ mLastDownTime = SystemClock.uptimeMillis();
+ return fromTouchscreen(
+ MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_DOWN, x, y, 0));
+ }
+
private MotionEvent downEvent() {
mLastDownTime = SystemClock.uptimeMillis();
return fromTouchscreen(
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..c467ee949aeb 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -16,49 +16,99 @@
package com.android.server.display;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
+
+import static com.android.server.display.DisplayModeDirector.Vote.PRIORITY_FLICKER;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContextWrapper;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Looper;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.display.DisplayModeDirector.BrightnessObserver;
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
import com.android.server.display.DisplayModeDirector.Vote;
+import com.android.server.testutils.FakeDeviceConfigInterface;
import com.google.common.truth.Truth;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DisplayModeDirectorTest {
// The tolerance within which we consider something approximately equals.
+ private static final String TAG = "DisplayModeDirectorTest";
+ private static final boolean DEBUG = false;
private static final float FLOAT_TOLERANCE = 0.01f;
private Context mContext;
+ private FakesInjector mInjector;
+ private Handler mHandler;
+ @Rule
+ public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
+ final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
+ when(mContext.getContentResolver()).thenReturn(resolver);
+ mInjector = new FakesInjector();
+ mHandler = new Handler(Looper.getMainLooper());
}
private DisplayModeDirector createDirectorFromRefreshRateArray(
float[] refreshRates, int baseModeId) {
DisplayModeDirector director =
- new DisplayModeDirector(mContext, new Handler(Looper.getMainLooper()));
+ new DisplayModeDirector(mContext, mHandler, mInjector);
int displayId = 0;
Display.Mode[] modes = new Display.Mode[refreshRates.length];
for (int i = 0; i < refreshRates.length; i++) {
@@ -159,9 +209,9 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testBrightnessHasLowerPriorityThanUser() {
- assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
- assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_SIZE);
+ public void testFlickerHasLowerPriorityThanUser() {
+ assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
+ assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_SIZE);
int displayId = 0;
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
@@ -169,7 +219,7 @@ public class DisplayModeDirectorTest {
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(displayId, votes);
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
- votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
+ votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
@@ -177,7 +227,7 @@ public class DisplayModeDirectorTest {
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
- votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
+ votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
@@ -185,7 +235,7 @@ public class DisplayModeDirectorTest {
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
- votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
+ votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
@@ -193,7 +243,7 @@ public class DisplayModeDirectorTest {
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
- votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
+ votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
@@ -202,10 +252,10 @@ public class DisplayModeDirectorTest {
@Test
public void testAppRequestRefreshRateRange() {
- // Confirm that the app request range doesn't include low brightness or min refresh rate
- // settings, but does include everything else.
+ // Confirm that the app request range doesn't include flicker or min refresh rate settings,
+ // but does include everything else.
assertTrue(
- Vote.PRIORITY_LOW_BRIGHTNESS < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ PRIORITY_FLICKER < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
@@ -216,7 +266,7 @@ public class DisplayModeDirectorTest {
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(displayId, votes);
- votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
+ votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
@@ -302,4 +352,343 @@ public class DisplayModeDirectorTest {
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
}
+
+ @Test
+ public void testBrightnessObserverGetsUpdatedRefreshRatesForZone() {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
+ SensorManager sensorManager = createMockSensorManager(createLightSensor());
+
+ final int initialRefreshRate = 60;
+ mInjector.getDeviceConfig().setRefreshRateInLowZone(initialRefreshRate);
+ director.start(sensorManager);
+ assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
+ .isEqualTo(initialRefreshRate);
+
+ final int updatedRefreshRate = 90;
+ mInjector.getDeviceConfig().setRefreshRateInLowZone(updatedRefreshRate);
+ // Need to wait for the property change to propagate to the main thread.
+ waitForIdleSync();
+ assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
+ .isEqualTo(updatedRefreshRate);
+ }
+
+ @Test
+ public void testBrightnessObserverThresholdsInZone() {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
+ SensorManager sensorManager = createMockSensorManager(createLightSensor());
+
+ final int[] initialDisplayThresholds = { 10 };
+ final int[] initialAmbientThresholds = { 20 };
+
+ final FakeDeviceConfig config = mInjector.getDeviceConfig();
+ config.setLowDisplayBrightnessThresholds(initialDisplayThresholds);
+ config.setLowAmbientBrightnessThresholds(initialAmbientThresholds);
+ director.start(sensorManager);
+
+ assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
+ .isEqualTo(initialDisplayThresholds);
+ assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
+ .isEqualTo(initialAmbientThresholds);
+
+ final int[] updatedDisplayThresholds = { 9, 14 };
+ final int[] updatedAmbientThresholds = { -1, 19 };
+ config.setLowDisplayBrightnessThresholds(updatedDisplayThresholds);
+ config.setLowAmbientBrightnessThresholds(updatedAmbientThresholds);
+ // Need to wait for the property change to propagate to the main thread.
+ waitForIdleSync();
+ assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
+ .isEqualTo(updatedDisplayThresholds);
+ assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
+ .isEqualTo(updatedAmbientThresholds);
+ }
+
+ @Test
+ public void testLockFpsForLowZone() throws Exception {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ setPeakRefreshRate(90);
+ director.getSettingsObserver().setDefaultRefreshRate(90);
+ director.getBrightnessObserver().setDefaultDisplayState(true);
+
+ final FakeDeviceConfig config = mInjector.getDeviceConfig();
+ config.setRefreshRateInLowZone(90);
+ config.setLowDisplayBrightnessThresholds(new int[] { 10 });
+ config.setLowAmbientBrightnessThresholds(new int[] { 20 });
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+
+ director.start(sensorManager);
+
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
+ .registerListener(
+ listenerCaptor.capture(),
+ eq(lightSensor),
+ anyInt(),
+ any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ setBrightness(10);
+ // Sensor reads 20 lux,
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
+
+ Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
+ assertVoteForRefreshRateLocked(vote, 90 /*fps*/);
+
+ setBrightness(125);
+ // Sensor reads 1000 lux,
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
+
+ vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
+ assertThat(vote).isNull();
+ }
+
+ @Test
+ public void testLockFpsForHighZone() throws Exception {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ setPeakRefreshRate(90 /*fps*/);
+ director.getSettingsObserver().setDefaultRefreshRate(90);
+ director.getBrightnessObserver().setDefaultDisplayState(true);
+
+ final FakeDeviceConfig config = mInjector.getDeviceConfig();
+ config.setRefreshRateInHighZone(60);
+ config.setHighDisplayBrightnessThresholds(new int[] { 255 });
+ config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+
+ director.start(sensorManager);
+
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
+ .registerListener(
+ listenerCaptor.capture(),
+ eq(lightSensor),
+ anyInt(),
+ any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ setBrightness(100);
+ // Sensor reads 2000 lux,
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
+
+ Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
+ assertThat(vote).isNull();
+
+ setBrightness(255);
+ // Sensor reads 9000 lux,
+ listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
+
+ vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
+ assertVoteForRefreshRateLocked(vote, 60 /*fps*/);
+ }
+
+ private void assertVoteForRefreshRateLocked(Vote vote, float refreshRate) {
+ assertThat(vote).isNotNull();
+ final DisplayModeDirector.RefreshRateRange expectedRange =
+ new DisplayModeDirector.RefreshRateRange(refreshRate, refreshRate);
+ assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
+ }
+
+ private static class FakeDeviceConfig extends FakeDeviceConfigInterface {
+ @Override
+ public String getProperty(String namespace, String name) {
+ Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
+ return super.getProperty(namespace, name);
+ }
+
+ @Override
+ public void addOnPropertiesChangedListener(
+ String namespace,
+ Executor executor,
+ DeviceConfig.OnPropertiesChangedListener listener) {
+ Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
+ super.addOnPropertiesChangedListener(namespace, executor, listener);
+ }
+
+ void setRefreshRateInLowZone(int fps) {
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_LOW_ZONE,
+ String.valueOf(fps));
+ }
+
+ void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
+ String thresholds = toPropertyValue(brightnessThresholds);
+
+ if (DEBUG) {
+ Slog.e(TAG, "Brightness Thresholds = " + thresholds);
+ }
+
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS,
+ thresholds);
+ }
+
+ void setLowAmbientBrightnessThresholds(int[] ambientThresholds) {
+ String thresholds = toPropertyValue(ambientThresholds);
+
+ if (DEBUG) {
+ Slog.e(TAG, "Ambient Thresholds = " + thresholds);
+ }
+
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS,
+ thresholds);
+ }
+
+ void setRefreshRateInHighZone(int fps) {
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_HIGH_ZONE,
+ String.valueOf(fps));
+ }
+
+ void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
+ String thresholds = toPropertyValue(brightnessThresholds);
+
+ if (DEBUG) {
+ Slog.e(TAG, "Brightness Thresholds = " + thresholds);
+ }
+
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS,
+ thresholds);
+ }
+
+ void setHighAmbientBrightnessThresholds(int[] ambientThresholds) {
+ String thresholds = toPropertyValue(ambientThresholds);
+
+ if (DEBUG) {
+ Slog.e(TAG, "Ambient Thresholds = " + thresholds);
+ }
+
+ putPropertyAndNotify(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS,
+ thresholds);
+ }
+
+ @NonNull
+ private static String toPropertyValue(@NonNull int[] intArray) {
+ return Arrays.stream(intArray)
+ .mapToObj(Integer::toString)
+ .collect(Collectors.joining(","));
+ }
+ }
+
+ private void setBrightness(int brightness) {
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,
+ brightness);
+ mInjector.notifyBrightnessChanged();
+ waitForIdleSync();
+ }
+
+ private void setPeakRefreshRate(float fps) {
+ Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
+ fps);
+ mInjector.notifyPeakRefreshRateChanged();
+ waitForIdleSync();
+ }
+
+ private static SensorManager createMockSensorManager(Sensor... sensors) {
+ SensorManager sensorManager = Mockito.mock(SensorManager.class);
+ when(sensorManager.getSensorList(anyInt())).then((invocation) -> {
+ List<Sensor> requestedSensors = new ArrayList<>();
+ int type = invocation.getArgument(0);
+ for (Sensor sensor : sensors) {
+ if (sensor.getType() == type || type == Sensor.TYPE_ALL) {
+ requestedSensors.add(sensor);
+ }
+ }
+ return requestedSensors;
+ });
+
+ when(sensorManager.getDefaultSensor(anyInt())).then((invocation) -> {
+ int type = invocation.getArgument(0);
+ for (Sensor sensor : sensors) {
+ if (sensor.getType() == type) {
+ return sensor;
+ }
+ }
+ return null;
+ });
+ return sensorManager;
+ }
+
+ private static Sensor createLightSensor() {
+ try {
+ return TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
+ } catch (Exception e) {
+ // There's nothing we can do if this fails, just throw a RuntimeException so that we
+ // don't have to mark every function that might call this as throwing Exception
+ throw new RuntimeException("Failed to create a light sensor", e);
+ }
+ }
+
+ private void waitForIdleSync() {
+ mHandler.runWithScissors(() -> { }, 500 /*timeout*/);
+ }
+
+ static class FakesInjector implements DisplayModeDirector.Injector {
+ private final FakeDeviceConfig mDeviceConfig;
+ private ContentObserver mBrightnessObserver;
+ private ContentObserver mPeakRefreshRateObserver;
+
+ FakesInjector() {
+ mDeviceConfig = new FakeDeviceConfig();
+ }
+
+ @NonNull
+ public FakeDeviceConfig getDeviceConfig() {
+ return mDeviceConfig;
+ }
+
+ @Override
+ public void registerBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ if (mBrightnessObserver != null) {
+ throw new IllegalStateException("Tried to register a second brightness observer");
+ }
+ mBrightnessObserver = observer;
+ }
+
+ @Override
+ public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ mBrightnessObserver = null;
+ }
+
+ void notifyBrightnessChanged() {
+ if (mBrightnessObserver != null) {
+ mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI);
+ }
+ }
+
+ @Override
+ public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ mPeakRefreshRateObserver = observer;
+ }
+
+ void notifyPeakRefreshRateChanged() {
+ if (mPeakRefreshRateObserver != null) {
+ mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
+ PEAK_REFRESH_RATE_URI);
+ }
+ }
+
+ @Override
+ public boolean isDeviceInteractive(@NonNull Context context) {
+ return true;
+ }
+ }
}
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 ba851992cbad..2c2fdcaab340 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -519,10 +519,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/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d244e687c8b8..d7897dbb6133 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -77,6 +77,7 @@ import com.android.server.SystemService;
import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.BatteryReceiver;
+import com.android.server.power.PowerManagerService.BinderService;
import com.android.server.power.PowerManagerService.Injector;
import com.android.server.power.PowerManagerService.NativeWrapper;
import com.android.server.power.PowerManagerService.UserSwitchedReceiver;
@@ -173,6 +174,7 @@ public class PowerManagerServiceTest {
when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(false);
when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true);
when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn("");
+ when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true);
mDisplayPowerRequest = new DisplayPowerRequest();
addLocalServiceMock(LightsManager.class, mLightsManagerMock);
@@ -967,4 +969,72 @@ public class PowerManagerServiceTest {
assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test2"))
.isFalse();
}
+
+ @Test
+ public void testIsAmbientDisplaySuppressedForTokenByApp_ambientDisplayUnavailable()
+ throws Exception {
+ createService();
+ when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(false);
+
+ BinderService service = mService.getBinderServiceInstance();
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid()))
+ .isFalse();
+ }
+
+ @Test
+ public void testIsAmbientDisplaySuppressedForTokenByApp_default()
+ throws Exception {
+ createService();
+
+ BinderService service = mService.getBinderServiceInstance();
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid()))
+ .isFalse();
+ }
+
+ @Test
+ public void testIsAmbientDisplaySuppressedForTokenByApp_suppressedByCallingApp()
+ throws Exception {
+ createService();
+ BinderService service = mService.getBinderServiceInstance();
+ service.suppressAmbientDisplay("test", true);
+
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid()))
+ .isTrue();
+ // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app.
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", /* appUid= */ 123))
+ .isFalse();
+ }
+
+ @Test
+ public void testIsAmbientDisplaySuppressedForTokenByApp_notSuppressedByCallingApp()
+ throws Exception {
+ createService();
+ BinderService service = mService.getBinderServiceInstance();
+ service.suppressAmbientDisplay("test", false);
+
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid()))
+ .isFalse();
+ // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app.
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", /* appUid= */ 123))
+ .isFalse();
+ }
+
+ @Test
+ public void testIsAmbientDisplaySuppressedForTokenByApp_multipleTokensSuppressedByCallingApp()
+ throws Exception {
+ createService();
+ BinderService service = mService.getBinderServiceInstance();
+ service.suppressAmbientDisplay("test1", true);
+ service.suppressAmbientDisplay("test2", true);
+
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test1", Binder.getCallingUid()))
+ .isTrue();
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test2", Binder.getCallingUid()))
+ .isTrue();
+ // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app.
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test1", /* appUid= */ 123))
+ .isFalse();
+ assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test2", /* appUid= */ 123))
+ .isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
index 614949c91b9a..1494642edb56 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
@@ -79,7 +79,9 @@ public class UriGrantsManagerServiceTest {
@Before
public void setUp() throws Exception {
mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext());
- mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService();
+ mService = UriGrantsManagerService
+ .createForTest(mContext, mContext.getFilesDir())
+ .getLocalService();
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index a07e60ce838e..1ced467dffa1 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -141,10 +141,13 @@ public class AppStandbyControllerTests {
private AppStandbyController mController;
private CountDownLatch mStateChangedLatch = new CountDownLatch(1);
+ private String mLatchPkgName = null;
private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() {
@Override
public void onAppIdleStateChanged(String packageName, int userId,
boolean idle, int bucket, int reason) {
+ // Ignore events not related to mLatchPkgName, if set.
+ if (mLatchPkgName != null && !mLatchPkgName.equals(packageName)) return;
mStateChangedLatch.countDown();
}
};
@@ -387,6 +390,7 @@ public class AppStandbyControllerTests {
mInjector.mElapsedRealtime, false));
controller.addListener(mListener);
+ mLatchPkgName = null;
return controller;
}
@@ -1390,7 +1394,7 @@ public class AppStandbyControllerTests {
@Test
public void testUnexemptedSyncScheduled() throws Exception {
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.addListener(mListener);
assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER,
getStandbyBucket(mController, PACKAGE_1));
@@ -1402,7 +1406,7 @@ public class AppStandbyControllerTests {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
assertEquals("Unexempted sync scheduled should not elevate a non Never bucket",
@@ -1413,7 +1417,7 @@ public class AppStandbyControllerTests {
public void testExemptedSyncScheduled() throws Exception {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
mInjector.mDeviceIdleMode = true;
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled in doze should set bucket to working set",
@@ -1421,7 +1425,7 @@ public class AppStandbyControllerTests {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
mInjector.mDeviceIdleMode = false;
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled while not in doze should set bucket to active",
@@ -1590,10 +1594,19 @@ public class AppStandbyControllerTests {
}
private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception {
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(pkg);
mController.setAppStandbyBucket(pkg, user, bucket, reason);
mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
assertEquals("Failed to set package bucket", bucket,
getStandbyBucket(mController, PACKAGE_1));
}
+
+ private void rearmLatch(String pkgName) {
+ mLatchPkgName = pkgName;
+ mStateChangedLatch = new CountDownLatch(1);
+ }
+
+ private void rearmLatch() {
+ rearmLatch(null);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java b/services/tests/servicestests/utils/com/android/server/testutils/FakeDeviceConfigInterface.java
index 2904a5b73646..a67f64596ef5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/utils/FakeDeviceConfigInterface.java
+++ b/services/tests/servicestests/utils/com/android/server/testutils/FakeDeviceConfigInterface.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.wm.utils;
+package com.android.server.testutils;
import android.annotation.NonNull;
import android.provider.DeviceConfig;
@@ -22,6 +22,7 @@ import android.util.ArrayMap;
import android.util.Pair;
import com.android.internal.util.Preconditions;
+import com.android.server.utils.DeviceConfigInterface;
import java.lang.reflect.Constructor;
import java.util.HashMap;
@@ -122,6 +123,19 @@ public class FakeDeviceConfigInterface implements DeviceConfigInterface {
}
@Override
+ public float getFloat(String namespace, String name, float defaultValue) {
+ String value = getProperty(namespace, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ try {
+ return Float.parseFloat(value);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ @Override
public boolean getBoolean(String namespace, String name, boolean defaultValue) {
String value = getProperty(namespace, name);
return value != null ? Boolean.parseBoolean(value) : defaultValue;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index abcc14c6be93..d088f37b69ba 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -103,6 +103,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
1 << 30);
+ private InjectableSystemClock mSystemClock = new FakeSystemClock();
private NotificationManagerService mService;
private String mPkg = "com.android.server.notification";
@@ -154,7 +155,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
assertTrue(accessibilityManager.isEnabled());
mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger,
- mNotificationInstanceIdSequence));
+ mSystemClock, mNotificationInstanceIdSequence));
mService.setAudioManager(mAudioManager);
mService.setVibrator(mVibrator);
mService.setSystemReady(true);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java b/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java
new file mode 100644
index 000000000000..c960f1766612
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java
@@ -0,0 +1,111 @@
+/*
+ * 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.notification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A fake {@link InjectableSystemClock}
+ *
+ * Attempts to simulate the behavior of a real system clock. Time can be moved forward but not
+ * backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync.
+ *
+ * Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with
+ * every call to {@link #advanceTime(long)}. Thread time always lags by 50% of the uptime
+ * advancement to simulate time loss due to scheduling.
+ *
+ * @hide
+ */
+public class FakeSystemClock implements InjectableSystemClock {
+ private long mUptimeMillis = 10000;
+ private long mElapsedRealtime = 10000;
+ private long mCurrentThreadTimeMillis = 10000;
+
+ private long mCurrentTimeMillis = 1555555500000L;
+
+ private final List<ClockTickListener> mListeners = new ArrayList<>();
+ @Override
+ public long uptimeMillis() {
+ return mUptimeMillis;
+ }
+
+ @Override
+ public long elapsedRealtime() {
+ return mElapsedRealtime;
+ }
+
+ @Override
+ public long elapsedRealtimeNanos() {
+ return mElapsedRealtime * 1000000 + 447;
+ }
+
+ @Override
+ public long currentThreadTimeMillis() {
+ return mCurrentThreadTimeMillis;
+ }
+
+ @Override
+ public long currentTimeMillis() {
+ return mCurrentTimeMillis;
+ }
+
+ public void setUptimeMillis(long uptime) {
+ advanceTime(uptime - mUptimeMillis);
+ }
+
+ public void setCurrentTimeMillis(long millis) {
+ mCurrentTimeMillis = millis;
+ }
+
+ public void advanceTime(long uptime) {
+ advanceTime(uptime, 0);
+ }
+
+ public void advanceTime(long uptime, long sleepTime) {
+ if (uptime < 0 || sleepTime < 0) {
+ throw new IllegalArgumentException("Time cannot go backwards.");
+ }
+
+ if (uptime > 0 || sleepTime > 0) {
+ mUptimeMillis += uptime;
+ mElapsedRealtime += uptime + sleepTime;
+ mCurrentTimeMillis += uptime + sleepTime;
+
+ mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5);
+
+ for (ClockTickListener listener : mListeners) {
+ listener.onClockTick();
+ }
+ }
+ }
+
+ public void addListener(ClockTickListener listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeListener(ClockTickListener listener) {
+ mListeners.remove(listener);
+ }
+
+ public interface ClockTickListener {
+ void onClockTick();
+ }
+
+ private static final long START_TIME = 10000;
+}
+
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 24384b1d4f31..4259831c15f8 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -199,6 +199,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Consumer;
@@ -287,18 +288,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
1 << 30);
@Mock
StatusBarManagerInternal mStatusBar;
+ private final FakeSystemClock mSystemClock = new FakeSystemClock();
// Use a Testable subclass so we can simulate calls from the system without failing.
private static class TestableNotificationManagerService extends NotificationManagerService {
int countSystemChecks = 0;
boolean isSystemUid = true;
int countLogSmartSuggestionsVisible = 0;
+ // If true, don't enqueue the PostNotificationRunnables, just trap them
+ boolean trapEnqueuedNotifications = false;
+ final ArrayList<NotificationManagerService.PostNotificationRunnable> trappedRunnables =
+ new ArrayList<>();
@Nullable
NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
- TestableNotificationManagerService(Context context, NotificationRecordLogger logger,
+ TestableNotificationManagerService(
+ Context context,
+ NotificationRecordLogger logger,
+ InjectableSystemClock systemClock,
InstanceIdSequence notificationInstanceIdSequence) {
- super(context, logger, notificationInstanceIdSequence);
+ super(context, logger, systemClock, notificationInstanceIdSequence);
}
RankingHelper getRankingHelper() {
@@ -353,6 +362,23 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
return new String[] {PKG_O};
}
+ @Override
+ protected void postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record,
+ PostNotificationRunnable runnable) {
+ if (trapEnqueuedNotifications) {
+ trappedRunnables.add(runnable);
+ return;
+ }
+
+ super.postPostNotificationRunnableMaybeDelayedLocked(record, runnable);
+ }
+
+ void drainTrappedRunnableQueue() {
+ for (Runnable r : trappedRunnables) {
+ getWorkHandler().post(r);
+ }
+ }
+
private void setNotificationAssistantAccessGrantedCallback(
@Nullable NotificationAssistantAccessGrantedCallback callback) {
this.mNotificationAssistantAccessGrantedCallback = callback;
@@ -402,7 +428,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
- mNotificationInstanceIdSequence);
+ mSystemClock, mNotificationInstanceIdSequence);
// Use this testable looper.
mTestableLooper = TestableLooper.get(this);
@@ -1344,10 +1370,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
sbn.getNotification(), sbn.getUserId());
- Thread.sleep(1); // make sure the system clock advances before the next step
+ mSystemClock.advanceTime(1);
// THEN it is canceled
mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
- Thread.sleep(1); // here too
+ mSystemClock.advanceTime(1);
// THEN it is posted again (before the cancel has a chance to finish)
mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
sbn.getNotification(), sbn.getUserId());
@@ -1362,6 +1388,60 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testChangeSystemTimeAfterPost_thenCancel_noFgs() throws Exception {
+ // GIVEN time X
+ mSystemClock.setCurrentTimeMillis(10000);
+
+ // GIVEN a notification is posted
+ final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
+ sbn.getNotification(), sbn.getUserId());
+ mSystemClock.advanceTime(1);
+ waitForIdle();
+
+ // THEN the system time is changed to an earlier time
+ mSystemClock.setCurrentTimeMillis(5000);
+
+ // THEN a cancel is requested
+ mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+
+ // It should work
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifs.length);
+ assertEquals(0, mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testChangeSystemTimeAfterPost_thenCancel_fgs() throws Exception {
+ // GIVEN time X
+ mSystemClock.setCurrentTimeMillis(10000);
+
+ // GIVEN a notification is posted
+ final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
+ sbn.getNotification().flags =
+ Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
+ sbn.getNotification(), sbn.getUserId());
+ mSystemClock.advanceTime(1);
+ waitForIdle();
+
+ // THEN the system time is changed to an earlier time
+ mSystemClock.setCurrentTimeMillis(5000);
+
+ // THEN a cancel is requested
+ mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+
+ // It should work
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifs.length);
+ assertEquals(0, mService.getNotificationRecordCount());
+ }
+
+ @Test
public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
mBinderService.enqueueNotificationWithTag(PKG, PKG,
"testCancelNotificationWhilePostedAndEnqueued", 0,
@@ -1383,6 +1463,56 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testDelayCancelWhenEnqueuedHasNotPosted() throws Exception {
+ // Don't allow PostNotificationRunnables to execute so we can set up problematic state
+ mService.trapEnqueuedNotifications = true;
+ // GIVEN an enqueued notification
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testDelayCancelWhenEnqueuedHasNotPosted", 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ mSystemClock.advanceTime(1);
+ // WHEN a cancel is requested before it has posted
+ mBinderService.cancelNotificationWithTag(PKG, PKG,
+ "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
+
+ waitForIdle();
+
+ // THEN the cancel notification runnable is captured and associated with that record
+ ArrayMap<NotificationRecord,
+ ArrayList<NotificationManagerService.CancelNotificationRunnable>> delayed =
+ mService.mDelayedCancelations;
+ Set<NotificationRecord> keySet = delayed.keySet();
+ assertEquals(1, keySet.size());
+ }
+
+ @Test
+ public void testDelayedCancelsExecuteAfterPost() throws Exception {
+ // Don't allow PostNotificationRunnables to execute so we can set up problematic state
+ mService.trapEnqueuedNotifications = true;
+ // GIVEN an enqueued notification
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testDelayCancelWhenEnqueuedHasNotPosted", 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ mSystemClock.advanceTime(1);
+ // WHEN a cancel is requested before it has posted
+ mBinderService.cancelNotificationWithTag(PKG, PKG,
+ "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0);
+
+ waitForIdle();
+
+ // We're now in a state with an a notification awaiting PostNotificationRunnable to execute
+ // WHEN the PostNotificationRunnable is allowed to execute
+ mService.drainTrappedRunnableQueue();
+ waitForIdle();
+
+ // THEN the cancel executes and the notification is removed
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifs.length);
+ assertEquals(0, mService.getNotificationRecordCount());
+ }
+
+ @Test
public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
NotificationRecord r = generateNotificationRecord(null);
final StatusBarNotification sbn = r.getSbn();
@@ -2529,8 +2659,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testHasCompanionDevice_noService() {
- mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
- mNotificationInstanceIdSequence);
+ mService =
+ new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
+ mSystemClock, mNotificationInstanceIdSequence);
assertFalse(mService.hasCompanionDevice(mListener));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index a118e0df1338..3b1059761357 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -96,6 +96,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableContentResolver;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Pair;
import android.util.StatsEvent;
import android.util.Xml;
@@ -3284,7 +3285,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
channel2.setImportantConversation(true);
mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false);
- List<ConversationChannelWrapper> convos = mHelper.getConversations(false);
+ List<ConversationChannelWrapper> convos =
+ mHelper.getConversations(IntArray.wrap(new int[] {0}), false);
assertEquals(3, convos.size());
assertTrue(conversationWrapperContainsChannel(convos, channel));
@@ -3293,6 +3295,44 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testGetConversations_multiUser() {
+ String convoId = "convo";
+ NotificationChannel messages =
+ new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false);
+
+ NotificationChannel messagesUser10 =
+ new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(
+ PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesUser10, true, false);
+
+ NotificationChannel messagesFromB =
+ new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT);
+ messagesFromB.setConversationId(messages.getId(), "different convo");
+ mHelper.createNotificationChannel(PKG_O, UID_O, messagesFromB, true, false);
+
+ NotificationChannel messagesFromBUser10 =
+ new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT);
+ messagesFromBUser10.setConversationId(messagesUser10.getId(), "different convo");
+ mHelper.createNotificationChannel(
+ PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesFromBUser10, true, false);
+
+
+ List<ConversationChannelWrapper> convos =
+ mHelper.getConversations(IntArray.wrap(new int[] {0}), false);
+
+ assertEquals(1, convos.size());
+ assertTrue(conversationWrapperContainsChannel(convos, messagesFromB));
+
+ convos =
+ mHelper.getConversations(IntArray.wrap(new int[] {0, UserHandle.getUserId(UID_O + UserHandle.PER_USER_RANGE)}), false);
+
+ assertEquals(2, convos.size());
+ assertTrue(conversationWrapperContainsChannel(convos, messagesFromB));
+ assertTrue(conversationWrapperContainsChannel(convos, messagesFromBUser10));
+ }
+
+ @Test
public void testGetConversations_notDemoted() {
String convoId = "convo";
NotificationChannel messages =
@@ -3322,7 +3362,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
channel2.setImportantConversation(true);
mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false);
- List<ConversationChannelWrapper> convos = mHelper.getConversations(false);
+ List<ConversationChannelWrapper> convos =
+ mHelper.getConversations(IntArray.wrap(new int[] {0}), false);
assertEquals(2, convos.size());
assertTrue(conversationWrapperContainsChannel(convos, channel));
@@ -3360,7 +3401,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
channel2.setConversationId(calls.getId(), convoId);
mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false);
- List<ConversationChannelWrapper> convos = mHelper.getConversations(true);
+ List<ConversationChannelWrapper> convos =
+ mHelper.getConversations(IntArray.wrap(new int[] {0}), true);
assertEquals(2, convos.size());
assertTrue(conversationWrapperContainsChannel(convos, channel));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 3281c3f4cfb9..ac2c6193c677 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -103,12 +103,14 @@ public class RoleObserverTest extends UiServiceTestCase {
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
1 << 30);
private List<UserInfo> mUsers;
+ private InjectableSystemClock mSystemClock = new FakeSystemClock();
private static class TestableNotificationManagerService extends NotificationManagerService {
TestableNotificationManagerService(Context context,
NotificationRecordLogger logger,
+ InjectableSystemClock systemClock,
InstanceIdSequence notificationInstanceIdSequence) {
- super(context, logger, notificationInstanceIdSequence);
+ super(context, logger, systemClock, notificationInstanceIdSequence);
}
@Override
@@ -136,7 +138,7 @@ public class RoleObserverTest extends UiServiceTestCase {
when(mUm.getUsers()).thenReturn(mUsers);
mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
- mNotificationInstanceIdSequence);
+ mSystemClock, mNotificationInstanceIdSequence);
mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor);
try {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index e1ce431fc97c..5b516a9de350 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -32,6 +32,7 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.timeout;
+import android.app.WaitResult;
import android.content.Intent;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -163,10 +164,15 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
@Test
public void testOnActivityLaunchFinished() {
+ // Assume that the process is started (ActivityBuilder has mocked the returned value of
+ // ATMS#getProcessController) but the activity has not attached process.
+ mTopActivity.app = null;
onActivityLaunched(mTopActivity);
notifyTransitionStarting(mTopActivity);
- notifyWindowsDrawn(mTopActivity);
+ final ActivityMetricsLogger.TransitionInfoSnapshot info = notifyWindowsDrawn(mTopActivity);
+ assertWithMessage("Warm launch").that(info.getLaunchState())
+ .isEqualTo(WaitResult.LAUNCH_STATE_WARM);
verifyOnActivityLaunchFinished(mTopActivity);
verifyNoMoreInteractions(mLaunchObserver);
@@ -201,7 +207,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
notifyActivityLaunching(noDrawnActivity.intent);
notifyActivityLaunched(START_SUCCESS, noDrawnActivity);
- noDrawnActivity.destroyIfPossible("test");
+ noDrawnActivity.mVisibleRequested = false;
mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);
verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity));
@@ -216,7 +222,9 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.logAppTransitionReportedDrawn(mTopActivity, false);
notifyTransitionStarting(mTopActivity);
// The pending fully drawn event should send when the actual windows drawn event occurs.
- notifyWindowsDrawn(mTopActivity);
+ final ActivityMetricsLogger.TransitionInfoSnapshot info = notifyWindowsDrawn(mTopActivity);
+ assertWithMessage("Hot launch").that(info.getLaunchState())
+ .isEqualTo(WaitResult.LAUNCH_STATE_HOT);
verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong());
verifyOnActivityLaunchFinished(mTopActivity);
@@ -260,8 +268,8 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyTransitionStarting(reasons);
}
- private void notifyWindowsDrawn(ActivityRecord r) {
- mActivityMetricsLogger.notifyWindowsDrawn(r, SystemClock.elapsedRealtimeNanos());
+ private ActivityMetricsLogger.TransitionInfoSnapshot notifyWindowsDrawn(ActivityRecord r) {
+ return mActivityMetricsLogger.notifyWindowsDrawn(r, SystemClock.elapsedRealtimeNanos());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index 880c486c15af..d42ab72a22b7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -20,6 +20,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
import static com.android.server.wm.DisplayArea.Type.ANY;
import static com.android.server.wm.DisplayArea.Type.BELOW_TASKS;
@@ -29,11 +32,15 @@ import static com.android.server.wm.DisplayArea.Type.typeOf;
import static com.android.server.wm.testing.Assert.assertThrows;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import android.content.pm.ActivityInfo;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowManager;
import org.junit.Rule;
import org.junit.Test;
@@ -97,6 +104,42 @@ public class DisplayAreaTest {
assertThrows(IllegalStateException.class, () -> checkChild(BELOW_TASKS, ANY));
}
+
+ @Test
+ public void testGetOrientation() {
+ final DisplayArea.Tokens area = new DisplayArea.Tokens(mWmsRule.getWindowManagerService(),
+ ABOVE_TASKS, "test");
+ final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY);
+ spyOn(token);
+ doReturn(mock(DisplayContent.class)).when(token).getDisplayContent();
+ doNothing().when(token).setParent(any());
+ final WindowState win = createWindowState(token);
+ spyOn(win);
+ doNothing().when(win).setParent(any());
+ win.mAttrs.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ token.addChild(win, 0);
+ area.addChild(token);
+
+ doReturn(true).when(win).isVisible();
+
+ assertEquals("Visible window can request orientation",
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
+ area.getOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR));
+
+ doReturn(false).when(win).isVisible();
+
+ assertEquals("Invisible window cannot request orientation",
+ ActivityInfo.SCREEN_ORIENTATION_NOSENSOR,
+ area.getOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR));
+ }
+
+ private WindowState createWindowState(WindowToken token) {
+ return new WindowState(mWmsRule.getWindowManagerService(), mock(Session.class),
+ new TestIWindow(), token, null /* parentWindow */, 0 /* appOp */, 0 /* seq*/,
+ new WindowManager.LayoutParams(), View.VISIBLE, 0 /* ownerId */, 0 /* showUserId */,
+ false /* ownerCanAddInternalSystemWindow */, null);
+ }
+
private WindowToken createWindowToken(int type) {
return new WindowToken(mWmsRule.getWindowManagerService(), new Binder(),
type, false /* persist */, null /* displayContent */,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 1948003a7499..d99606b704e4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -32,6 +32,7 @@ import static android.view.Display.FLAG_PRIVATE;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.DisplayCutout.fromBoundingRect;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
@@ -102,6 +103,7 @@ import android.view.IDisplayWindowRotationCallback;
import android.view.IDisplayWindowRotationController;
import android.view.ISystemGestureExclusionListener;
import android.view.IWindowManager;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl.Transaction;
@@ -1114,6 +1116,17 @@ public class DisplayContentTests extends WindowTestsBase {
assertTrue(mNavBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS,
ANIMATION_TYPE_FIXED_TRANSFORM));
+ // If the visibility of insets state is changed, the rotated state should be updated too.
+ final InsetsState rotatedState = app.getFixedRotationTransformInsetsState();
+ final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
+ assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(),
+ rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+ state.getSource(ITYPE_STATUS_BAR).setVisible(
+ !rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+ mDisplayContent.getInsetsStateController().notifyInsetsChanged();
+ assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(),
+ rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+
final Rect outFrame = new Rect();
final Rect outInsets = new Rect();
final Rect outStableInsets = new Rect();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 58d4104bf2b0..7e3613411b37 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -52,10 +52,13 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_RIGHT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.testng.Assert.expectThrows;
@@ -927,6 +930,25 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
@Test
+ public void testFixedRotationInsetsSourceFrame() {
+ final DisplayInfo info = mDisplayContent.getDisplayInfo();
+ info.rotation = mFrames.mRotation;
+ mDisplayContent.mBaseDisplayHeight = info.logicalHeight = mFrames.mDisplayHeight;
+ mDisplayContent.mBaseDisplayWidth = info.logicalWidth = mFrames.mDisplayWidth;
+ mDisplayContent.getInsetsStateController().onPostLayout();
+ mDisplayPolicy.beginLayoutLw(mFrames, mDisplayContent.getConfiguration().uiMode);
+ doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent)
+ .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
+ final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+ doReturn(mDisplayPolicy).when(mDisplayContent).getDisplayPolicy();
+ mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
+ final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+
+ assertEquals(DISPLAY_WIDTH, frame.width());
+ assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
+ }
+
+ @Test
public void testScreenDecorWindows() {
final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow");
mWindow.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index f53894ad9ec5..112b2e98a7f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -31,7 +31,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.util.Preconditions;
-import com.android.server.wm.utils.FakeDeviceConfigInterface;
+import com.android.server.testutils.FakeDeviceConfigInterface;
import org.junit.After;
import org.junit.Test;
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 90af8a1b3199..7d84920187a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -38,10 +38,13 @@ 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;
@@ -49,6 +52,8 @@ import android.view.test.InsetsModeSession;
import androidx.test.filters.SmallTest;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -222,6 +227,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);
}
@Test
@@ -309,6 +331,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 73ac408f7980..3db00189e525 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -30,6 +30,9 @@ 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;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -329,6 +332,26 @@ public class InsetsStateControllerTest extends WindowTestsBase {
assertNull(getController().getControlsForDispatch(app));
}
+ @Test
+ public void testTransientVisibilityOfFixedRotationState() {
+ final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final InsetsSourceProvider provider = getController().getSourceProvider(ITYPE_STATUS_BAR);
+ provider.setWindow(statusBar, null, null);
+
+ final InsetsState rotatedState = new InsetsState(app.getInsetsState(),
+ true /* copySources */);
+ spyOn(app.mToken);
+ doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
+ assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+
+ provider.getSource().setVisible(false);
+ mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR });
+
+ assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
+ assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
+ }
+
private InsetsStateController getController() {
return mDisplayContent.getInsetsStateController();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index f2771175b523..730e9beecf77 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -395,6 +395,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
// The rotation transform should be cleared after updating orientation with display.
assertFalse(activity.hasFixedRotationTransform());
assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
+
+ // Simulate swiping up recents (home) in different rotation.
+ final ActivityRecord home = mDefaultDisplay.getDefaultTaskDisplayArea().getHomeActivity();
+ mDefaultDisplay.setFixedRotationLaunchingApp(home, (mDefaultDisplay.getRotation() + 1) % 4);
+ mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
+ mDefaultDisplay.getDisplayId());
+ initializeRecentsAnimationController(mController, home);
+ assertTrue(home.hasFixedRotationTransform());
+
+ // Assume recents activity becomes invisible for some reason (e.g. screen off).
+ home.setVisible(false);
+ mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+ // Although there won't be a transition finish callback, the fixed rotation must be cleared.
+ assertFalse(home.hasFixedRotationTransform());
+ assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index a979c862a8e4..250dc2469be1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -568,6 +568,8 @@ public class SizeCompatTests extends ActivityTestsBase {
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+ params.setFitInsetsSides(0);
+ params.setFitInsetsTypes(0);
final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
WindowTestsBase.makeWindowVisible(w);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java
index 52100116df53..7a0ef0d7d7a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerConstantsTest.java
@@ -32,7 +32,7 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
-import com.android.server.wm.utils.FakeDeviceConfigInterface;
+import com.android.server.testutils.FakeDeviceConfigInterface;
import org.junit.After;
import org.junit.Before;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index da2d4d82481b..afe186cba0db 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -373,6 +373,14 @@ public class TelecomManager {
"android.telecom.extra.CALL_DISCONNECT_MESSAGE";
/**
+ * A string value for {@link #EXTRA_CALL_DISCONNECT_MESSAGE}, indicates the call was dropped by
+ * lower layers
+ * @hide
+ */
+ public static final String CALL_AUTO_DISCONNECT_MESSAGE_STRING =
+ "Call dropped by lower layers";
+
+ /**
* Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
* containing the component name of the associated connection service.
* @hide
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index 02597d548361..e67354982b05 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -96,6 +96,19 @@ public class StagedInstallInternalTest {
assertSessionReady(sessionId);
}
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
+ InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK",
+ Install.single(TestApp.AIncompleteSplit).setStaged());
+ }
+
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage()
+ throws Exception {
+ InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK",
+ Install.multi(TestApp.AIncompleteSplit, TestApp.B1, TestApp.Apex1).setStaged());
+ }
+
private static void assertSessionReady(int sessionId) {
assertSessionState(sessionId,
(session) -> assertThat(session.isStagedSessionReady()).isTrue());
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index b7c9e59bd3ac..8cfe187d387c 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -27,6 +27,7 @@ import android.cts.install.lib.host.InstallUtilsHost;
import com.android.ddmlib.Log;
import com.android.tests.rollback.host.AbandonSessionsRule;
+import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.ProcessInfo;
@@ -38,6 +39,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@@ -180,9 +184,55 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
assertThat(sessionIds.length).isEqualTo(3);
}
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
+ List<String> before = getStagingDirectories();
+ runPhase("testStagedInstallationShouldCleanUpOnValidationFailure");
+ List<String> after = getStagingDirectories();
+ assertThat(after).isEqualTo(before);
+ }
+
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage()
+ throws Exception {
+ List<String> before = getStagingDirectories();
+ runPhase("testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage");
+ List<String> after = getStagingDirectories();
+ assertThat(after).isEqualTo(before);
+ }
+
+ @Test
+ public void testOrphanedStagingDirectoryGetsCleanedUpOnReboot() throws Exception {
+ //create random directories in /data/app-staging folder
+ getDevice().enableAdbRoot();
+ getDevice().executeShellCommand("mkdir /data/app-staging/session_123");
+ getDevice().executeShellCommand("mkdir /data/app-staging/random_name");
+ getDevice().disableAdbRoot();
+
+ assertThat(getStagingDirectories()).isNotEmpty();
+ getDevice().reboot();
+ assertThat(getStagingDirectories()).isEmpty();
+ }
+
+ private List<String> getStagingDirectories() throws DeviceNotAvailableException {
+ String baseDir = "/data/app-staging";
+ try {
+ getDevice().enableAdbRoot();
+ return getDevice().getFileEntry(baseDir).getChildren(false)
+ .stream().filter(entry -> entry.getName().matches("session_\\d+"))
+ .map(entry -> entry.getName())
+ .collect(Collectors.toList());
+ } catch (Exception e) {
+ // Return an empty list if any error
+ return Collections.EMPTY_LIST;
+ } finally {
+ getDevice().disableAdbRoot();
+ }
+ }
+
private void restartSystemServer() throws Exception {
// Restart the system server
- final long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();
+ long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();
getDevice().enableAdbRoot(); // Need root to restart system server
assertThat(getDevice().executeShellCommand("am restart")).contains("Restart the system");
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java
index e482708e385b..a0a5a293f2e4 100644
--- a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java
+++ b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java
@@ -92,6 +92,14 @@ public class FakeSettingsProvider extends MockContentProvider {
}
/**
+ * Creates a {@link org.junit.rules.TestRule} that makes sure {@link #clearSettingsProvider()}
+ * is triggered before and after each test.
+ */
+ public static FakeSettingsProviderRule rule() {
+ return new FakeSettingsProviderRule();
+ }
+
+ /**
* This needs to be called before and after using the FakeSettingsProvider class.
*/
public static void clearSettingsProvider() {
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java
new file mode 100644
index 000000000000..c4e9545dfde2
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java
@@ -0,0 +1,76 @@
+/*
+ * 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.util.test;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit Rule helps keeping test {@link FakeSettingsProvider} clean.
+ *
+ * <p>It clears {@link FakeSettingsProvider} before and after each test. Example use:
+ * <pre class="code"><code class="java">
+ * public class ExampleTest {
+ *
+ * &#064;Rule public FakeSettingsProviderRule rule = FakeSettingsProvider.rule();
+ *
+ * &#064;Test
+ * public void shouldDoSomething() {
+ * ContextResolver cr = rule.mockContentResolver(mContext);
+ * Settings.Global.putInt(cr, "my_setting_name", 1);
+ * // Test code relying on my_setting_name value using cr
+ * }
+ * }
+ * </code></pre>
+ *
+ * @see FakeSettingsProvider
+ */
+public final class FakeSettingsProviderRule implements TestRule {
+
+ /** Prevent initialization outside {@link FakeSettingsProvider}. */
+ FakeSettingsProviderRule() {
+ }
+
+ /**
+ * Creates a {@link MockContentResolver} that uses the {@link FakeSettingsProvider} as the
+ * {@link Settings#AUTHORITY} provider.
+ */
+ public MockContentResolver mockContentResolver(Context context) {
+ MockContentResolver contentResolver = new MockContentResolver(context);
+ contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ return contentResolver;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ public void evaluate() throws Throwable {
+ FakeSettingsProvider.clearSettingsProvider();
+ try {
+ base.evaluate();
+ } finally {
+ FakeSettingsProvider.clearSettingsProvider();
+ }
+ }
+ };
+ }
+}